diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/Makefile | 8 | ||||
-rw-r--r-- | elf/neededtest.c | 22 | ||||
-rw-r--r-- | elf/neededtest2.c | 116 | ||||
-rw-r--r-- | elf/unload.c | 34 |
4 files changed, 169 insertions, 11 deletions
diff --git a/elf/Makefile b/elf/Makefile index 06ff79d30a..ad89103808 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -97,7 +97,8 @@ 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 unload2 lateglobal + $(tests-nodlopen-$(have-z-nodlopen)) neededtest neededtest2 \ + unload2 lateglobal tests-vis-yes = vismain tests-nodelete-yes = nodelete tests-nodlopen-yes = nodlopen @@ -268,10 +269,13 @@ LDFLAGS-loadtest = -rdynamic $(objpfx)loadtest.out: $(test-modules) $(objpfx)neededtest: $(libdl) - $(objpfx)neededtest.out: $(objpfx)neededobj1.so $(objpfx)neededobj2.so \ $(objpfx)neededobj3.so +$(objpfx)neededtest2: $(libdl) +$(objpfx)neededtest2.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/neededtest.c b/elf/neededtest.c index 98f69a3185..a33d243651 100644 --- a/elf/neededtest.c +++ b/elf/neededtest.c @@ -64,7 +64,7 @@ check_loaded_objects (const char **loaded) int main (void) { - void *obj2; + void *obj2[2]; void *obj3; const char *loaded[] = { NULL, NULL, NULL, NULL }; int errors = 0; @@ -84,7 +84,16 @@ main (void) loaded[2] = "neededobj3.so"; errors += check_loaded_objects (loaded); printf ("Now loading shared object neededobj2.so\n"); - obj2 = dlopen ("neededobj2.so", RTLD_LAZY); + obj2[0] = dlopen ("neededobj2.so", RTLD_LAZY); + if (obj2 == NULL) + { + printf ("%s\n", dlerror ()); + exit (1); + } + printf ("After loading neededobj2.so once\n"); + errors += check_loaded_objects (loaded); + printf ("And loading shared object neededobj2.so again\n"); + obj2[1] = dlopen ("neededobj2.so", RTLD_LAZY); if (obj2 == NULL) { printf ("%s\n", dlerror ()); @@ -92,12 +101,17 @@ main (void) } printf ("Again, this is what is in memory\n"); errors += check_loaded_objects (loaded); - printf ("Closing neededobj2.so\n"); - dlclose (obj2); + printf ("Closing neededobj2.so for the first time\n"); + dlclose (obj2[0]); errors += check_loaded_objects (loaded); printf ("Closing neededobj3.so\n"); dlclose (obj3); + loaded[2] = NULL; + errors += check_loaded_objects (loaded); + printf ("Closing neededobj2.so for the second time\n"); + dlclose (obj2[1]); loaded[0] = NULL; + loaded[1] = NULL; errors += check_loaded_objects (loaded); if (errors != 0) printf ("%d errors found\n", errors); diff --git a/elf/neededtest2.c b/elf/neededtest2.c new file mode 100644 index 0000000000..cf111bc303 --- /dev/null +++ b/elf/neededtest2.c @@ -0,0 +1,116 @@ +#include <dlfcn.h> +#include <libintl.h> +#include <link.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.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, count = %d\n", lm->l_name, (int) lm->l_opencount); + 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[2]; + 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 ("\nLoading shared object neededobj2.so\n"); + obj2 = dlopen ("neededobj2.so", RTLD_LAZY); + if (obj2 == NULL) + { + printf ("%s\n", dlerror ()); + exit (1); + } + loaded[0] = "neededobj1.so"; + loaded[1] = "neededobj2.so"; + errors += check_loaded_objects (loaded); + printf ("\nLoading shared object neededobj3.so\n"); + obj3[0] = dlopen( "neededobj3.so", RTLD_LAZY); + if (obj3[0] == NULL) + { + printf ("%s\n", dlerror ()); + exit (1); + } + loaded[2] = "neededobj3.so"; + errors += check_loaded_objects (loaded); + printf ("\nNow loading shared object neededobj3.so again\n"); + obj3[1] = dlopen ("neededobj3.so", RTLD_LAZY); + if (obj3[1] == NULL) + { + printf ("%s\n", dlerror ()); + exit (1); + } + errors += check_loaded_objects (loaded); + printf ("\nClosing neededobj3.so once\n"); + dlclose (obj3[0]); + errors += check_loaded_objects (loaded); + printf ("\nClosing neededobj2.so\n"); + dlclose (obj2); + errors += check_loaded_objects (loaded); + printf ("\nClosing neededobj3.so for the second time\n"); + dlclose (obj3[1]); + loaded[0] = NULL; + loaded[1] = NULL; + loaded[2] = NULL; + errors += check_loaded_objects (loaded); + if (errors != 0) + printf ("%d errors found\n", errors); + return errors; +} diff --git a/elf/unload.c b/elf/unload.c index 2789abd5bb..4fd82b7e3a 100644 --- a/elf/unload.c +++ b/elf/unload.c @@ -4,10 +4,18 @@ require it for glibc. */ #include <dlfcn.h> +#include <link.h> #include <mcheck.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); \ + fflush (stdout) + typedef struct { void *next; @@ -20,46 +28,62 @@ main (void) strct *testdat; int ret; int result = 0; + struct link_map *map; mtrace (); + puts ("\nBefore"); + OUT; + sohandle = dlopen ("unloadmod.so", RTLD_NOW | RTLD_GLOBAL); if (sohandle == NULL) { - printf ("first dlopen failed: %s\n", dlerror ()); + printf ("*** first dlopen failed: %s\n", dlerror ()); exit (1); } + puts ("\nAfter loading unloadmod.so"); + OUT; + testdat = dlsym (sohandle, "testdat"); testdat->next = (void *) -1; ret = dlclose (sohandle); if (ret != 0) { - puts ("first dlclose failed"); + puts ("*** first dlclose failed"); result = 1; } + puts ("\nAfter closing unloadmod.so"); + OUT; + sohandle = dlopen ("unloadmod.so", RTLD_NOW | RTLD_GLOBAL); if (sohandle == NULL) { - printf ("second dlopen failed: %s\n", dlerror ()); + printf ("*** second dlopen failed: %s\n", dlerror ()); exit (1); } + puts ("\nAfter loading unloadmod.so the second time"); + OUT; + testdat = dlsym (sohandle, "testdat"); if (testdat->next == (void *) -1) { - puts ("testdat->next == (void *) -1"); + puts ("*** testdat->next == (void *) -1"); result = 1; } ret = dlclose (sohandle); if (ret != 0) { - puts ("second dlclose failed"); + puts ("*** second dlclose failed"); result = 1; } + puts ("\nAfter closing unloadmod.so again"); + OUT; + return result; } |