diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/Makefile | 17 | ||||
-rw-r--r-- | elf/dl-close.c | 14 | ||||
-rw-r--r-- | elf/dl-load.c | 2 | ||||
-rw-r--r-- | elf/neededobj1.c | 4 | ||||
-rw-r--r-- | elf/neededobj2.c | 7 | ||||
-rw-r--r-- | elf/neededobj3.c | 9 | ||||
-rw-r--r-- | elf/neededtest.c | 104 |
7 files changed, 149 insertions, 8 deletions
diff --git a/elf/Makefile b/elf/Makefile index 917a745..d38524d 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -53,7 +53,8 @@ distribute := $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \ nodlopenmod.c nodelete.c nodelmod1.c nodelmod2.c \ nodelmod3.c nodelmod4.c nodlopen.c dl-osinfo.h \ reldepmod1.c reldepmod2.c reldepmod3.c reldepmod4.c \ - nextmod1.c nextmod2.c + nextmod1.c nextmod2.c \ + neededtest.c neededobj1.c neededobj2.c neededobj3.c include ../Makeconfig @@ -95,7 +96,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)) + $(tests-nodlopen-$(have-z-nodlopen)) neededtest tests-vis-yes = vismain tests-nodelete-yes = nodelete tests-nodlopen-yes = nodlopen @@ -105,7 +106,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ dep1 dep2 dep3 dep4 $(modules-vis-$(have-protected)) \ $(modules-nodelete-$(have-z-nodelete)) \ $(modules-nodlopen-$(have-z-nodlopen)) filtmod1 filtmod2 \ - reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2 + reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2 \ + neededobj1 neededobj2 neededobj3 modules-vis-yes = vismod1 vismod2 vismod3 modules-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4 modules-nodlopen-yes = nodlopenmod @@ -249,6 +251,10 @@ $(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) + # filtmod1.so has a special rule $(filter-out $(objpfx)filtmod1.so, $(test-modules)): $(objpfx)%.so: $(objpfx)%.os $(build-module) @@ -258,6 +264,11 @@ LDFLAGS-loadtest = -rdynamic $(objpfx)loadtest.out: $(test-modules) +$(objpfx)neededtest: $(libdl) + +$(objpfx)neededtest.out: $(objpfx)neededobj1.so $(objpfx)neededobj2.so \ + $(objpfx)neededobj3.so + $(objpfx)restest1: $(objpfx)testobj1.so $(objpfx)testobj1_1.so $(libdl) LDFLAGS-restest1 = -rdynamic diff --git a/elf/dl-close.c b/elf/dl-close.c index 8426e73..03c38d9 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -61,6 +61,9 @@ _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) { @@ -78,14 +81,17 @@ _dl_close (void *_map) "\n", NULL); } - --map->l_opencount; + /* 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; + __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/dl-load.c b/elf/dl-load.c index 81ac233..b2f5ad7 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -851,7 +851,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname, if (__builtin_expect (header->e_version, EV_CURRENT) != EV_CURRENT) LOSE (0, N_("ELF file version does not match current one")); - if (! __builtin_expect (elf_machine_matches_host (header->e_machine), 1)) + if (! __builtin_expect (elf_machine_matches_host (header), 1)) LOSE (0, N_("ELF file machine architecture does not match")); if (__builtin_expect (header->e_phentsize, sizeof (ElfW(Phdr))) != sizeof (ElfW(Phdr))) diff --git a/elf/neededobj1.c b/elf/neededobj1.c new file mode 100644 index 0000000..12c5184 --- /dev/null +++ b/elf/neededobj1.c @@ -0,0 +1,4 @@ +void +c_function (void) +{ +} diff --git a/elf/neededobj2.c b/elf/neededobj2.c new file mode 100644 index 0000000..22b0e4c --- /dev/null +++ b/elf/neededobj2.c @@ -0,0 +1,7 @@ +extern void c_function (void); + +void +b_function (void) +{ + c_function(); +} diff --git a/elf/neededobj3.c b/elf/neededobj3.c new file mode 100644 index 0000000..0fc94e2 --- /dev/null +++ b/elf/neededobj3.c @@ -0,0 +1,9 @@ +extern void b_function (void); +extern void c_function (void); + +void +a_function (void) +{ + b_function (); + c_function (); +} diff --git a/elf/neededtest.c b/elf/neededtest.c new file mode 100644 index 0000000..053d552 --- /dev/null +++ b/elf/neededtest.c @@ -0,0 +1,104 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dlfcn.h> +#include <link.h> + +static int +check_loaded_objects (const char **loaded) +{ + struct link_map *lm; + int n; + int *found = NULL; + int errors = 0; + + for (n = 0; loaded[n]; n++) + /* NOTHING */; + + if (n) + { + found = (int *) alloca (sizeof (int) * n); + memset (found, 0, sizeof (int) * n); + } + + printf(" Name\n"); + printf(" --------------------------------------------------------\n"); + for (lm = _r_debug.r_map; lm; lm = lm->l_next) + { + if (lm->l_name && lm->l_name[0]) + printf(" %s\n", lm->l_name); + if (lm->l_type == lt_loaded && lm->l_name) + { + int match = 0; + for (n = 0; loaded[n] != NULL; n++) + { + if (strcmp (basename (loaded[n]), basename (lm->l_name)) == 0) + { + found[n] = 1; + match = 1; + break; + } + } + + if (match == 0) + { + ++errors; + printf ("ERRORS: %s is not unloaded\n", lm->l_name); + } + } + } + + for (n = 0; loaded[n] != NULL; n++) + { + if (found[n] == 0) + { + ++errors; + printf ("ERRORS: %s is not loaded\n", loaded[n]); + } + } + + return errors; +} + +int +main (void) +{ + void *obj2; + void *obj3; + const char *loaded[] = { NULL, NULL, NULL, NULL }; + int errors = 0; + + printf ("\nThis is what is in memory now:\n"); + errors += check_loaded_objects (loaded); + printf( "Loading shared object neededobj3.so\n"); + obj3 = dlopen( "neededobj3.so", RTLD_LAZY); + if (obj3 == NULL) + { + printf ("%s\n", dlerror ()); + exit (1); + } + printf ("And this is what is now in memory\n"); + loaded[0] = "neededobj1.so"; + loaded[1] = "neededobj2.so"; + loaded[2] = "neededobj3.so"; + errors += check_loaded_objects (loaded); + printf ("Now loading shared object neededobj2.so\n"); + obj2 = dlopen ("neededobj2.so", RTLD_LAZY); + if (obj2 == NULL) + { + printf ("%s\n", dlerror ()); + exit (1); + } + printf ("Again, this is what is in memory\n"); + errors += check_loaded_objects (loaded); + printf ("Closing neededobj2.so\n"); + dlclose (obj2); + errors += check_loaded_objects (loaded); + printf ("Closing neededobj3.so\n"); + dlclose (obj3); + loaded[0] = NULL; + errors += check_loaded_objects (loaded); + if (errors != 0) + printf ("%d errorss found\n", errors); + return errors; +} |