diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/Makefile | 12 | ||||
-rw-r--r-- | elf/dl-close.c | 14 | ||||
-rw-r--r-- | elf/unload2.c | 56 | ||||
-rw-r--r-- | elf/unload2dep.c | 4 | ||||
-rw-r--r-- | elf/unload2mod.c | 7 |
5 files changed, 79 insertions, 14 deletions
diff --git a/elf/Makefile b/elf/Makefile index d38524d040..033b0dcce9 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -54,7 +54,8 @@ distribute := $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \ nodelmod3.c nodelmod4.c nodlopen.c dl-osinfo.h \ reldepmod1.c reldepmod2.c reldepmod3.c reldepmod4.c \ nextmod1.c nextmod2.c \ - neededtest.c neededobj1.c neededobj2.c neededobj3.c + neededobj1.c neededobj2.c neededobj3.c \ + unload2mod.c unload2dep.c include ../Makeconfig @@ -96,7 +97,7 @@ ifeq (yes,$(build-shared)) tests = loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ constload1 order $(tests-vis-$(have-protected)) noload filter unload \ reldep reldep2 reldep3 next $(tests-nodelete-$(have-z-nodelete)) \ - $(tests-nodlopen-$(have-z-nodlopen)) neededtest + $(tests-nodlopen-$(have-z-nodlopen)) neededtest unload2 tests-vis-yes = vismain tests-nodelete-yes = nodelete tests-nodlopen-yes = nodlopen @@ -107,7 +108,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ $(modules-nodelete-$(have-z-nodelete)) \ $(modules-nodlopen-$(have-z-nodlopen)) filtmod1 filtmod2 \ reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2 \ - neededobj1 neededobj2 neededobj3 + neededobj1 neededobj2 neededobj3 unload2mod unload2dep modules-vis-yes = vismod1 vismod2 vismod3 modules-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4 modules-nodlopen-yes = nodlopenmod @@ -250,10 +251,10 @@ $(objpfx)dep2.so: $(objpfx)dep3.so $(objpfx)dep4.so $(objpfx)dep4.so: $(objpfx)dep3.so $(objpfx)nodelmod3.so: $(objpfx)nodelmod4.so $(objpfx)nextmod1.so: $(libdl) - $(objpfx)neededobj1.so: $(libdl) $(objpfx)neededobj2.so: $(objpfx)neededobj1.so $(libdl) $(objpfx)neededobj3.so: $(objpfx)neededobj1.so $(objpfx)neededobj2.so $(libdl) +$(objpfx)unload2mod.so: $(objpfx)unload2dep.so # filtmod1.so has a special rule $(filter-out $(objpfx)filtmod1.so, $(test-modules)): $(objpfx)%.so: $(objpfx)%.os @@ -352,3 +353,6 @@ $(objpfx)reldep3: $(libdl) $(objpfx)reldep3.out: $(objpfx)reldepmod1.so $(objpfx)reldepmod4.so $(objpfx)next: $(objpfx)nextmod1.so $(objpfx)nextmod2.so $(libdl) + +$(objpfx)unload2: $(libdl) +$(objpfx)unload2.out: $(objpfx)unload2mod.so $(objpfx)unload2dep.so diff --git a/elf/dl-close.c b/elf/dl-close.c index 03c38d906f..8426e73ec9 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -61,9 +61,6 @@ _dl_close (void *_map) /* Acquire the lock. */ __libc_lock_lock (_dl_load_lock); - list = map->l_searchlist.r_list; - nsearchlist = map->l_searchlist.r_nlist; - /* Decrement the reference count. */ if (map->l_opencount > 1 || map->l_type != lt_loaded) { @@ -81,17 +78,14 @@ _dl_close (void *_map) "\n", NULL); } - /* Even if we don't unload it now, we still have to decrement - `l_opencount' of the dependencies. Otherwise, they may not - get unloaded later. */ - for (i = 0; i < nsearchlist; ++i) - if (! (list[i]->l_flags_1 & DF_1_NODELETE)) - --list[i]->l_opencount; - + --map->l_opencount; __libc_lock_unlock (_dl_load_lock); return; } + list = map->l_searchlist.r_list; + nsearchlist = map->l_searchlist.r_nlist; + rellist = map->l_reldeps; nrellist = map->l_reldepsact; diff --git a/elf/unload2.c b/elf/unload2.c new file mode 100644 index 0000000000..b544e794c8 --- /dev/null +++ b/elf/unload2.c @@ -0,0 +1,56 @@ +#include <dlfcn.h> +#include <elf.h> +#include <errno.h> +#include <error.h> +#include <link.h> +#include <stdio.h> +#include <stdlib.h> + +#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) + +int +main (void) +{ + void *h[3]; + struct link_map *map; + void (*fp) (void); + + h[0] = dlopen ("unload2mod.so", RTLD_LAZY); + h[1] = dlopen ("unload2mod.so", RTLD_LAZY); + if (h[0] == NULL || h[1] == NULL) + error (EXIT_FAILURE, errno, "cannot load \"unload2mod.so\""); + h[2] = dlopen ("unload2dep.so", RTLD_LAZY); + if (h[2] == NULL) + error (EXIT_FAILURE, errno, "cannot load \"unload2dep.so\""); + + puts ("\nAfter loading everything:"); + OUT; + + dlclose (h[0]); + + puts ("\nAfter unloading \"unload2mod.so\" once:"); + OUT; + + dlclose (h[1]); + + puts ("\nAfter unloading \"unload2mod.so\" twice:"); + OUT; + + fp = dlsym (h[2], "foo"); + puts ("\nnow calling `foo'"); + fflush (stdout); + fp (); + puts ("managed to call `foo'"); + fflush (stdout); + + dlclose (h[2]); + + puts ("\nAfter unloading \"unload2dep.so\":"); + OUT; + + return 0; +} diff --git a/elf/unload2dep.c b/elf/unload2dep.c new file mode 100644 index 0000000000..cd0130cacd --- /dev/null +++ b/elf/unload2dep.c @@ -0,0 +1,4 @@ +void +foo (void) +{ +} diff --git a/elf/unload2mod.c b/elf/unload2mod.c new file mode 100644 index 0000000000..eae278df96 --- /dev/null +++ b/elf/unload2mod.c @@ -0,0 +1,7 @@ +extern void foo (void); + +void +bar (void) +{ + foo (); +} |