diff options
Diffstat (limited to 'test/dlopen')
| -rw-r--r-- | test/dlopen/Makefile | 40 | ||||
| -rw-r--r-- | test/dlopen/Makefile.in | 82 | ||||
| -rw-r--r-- | test/dlopen/dltest.c | 2 | ||||
| -rw-r--r-- | test/dlopen/libA.c | 7 | ||||
| -rw-r--r-- | test/dlopen/libB.c | 7 | ||||
| -rw-r--r-- | test/dlopen/libC.c | 30 | ||||
| -rw-r--r-- | test/dlopen/libtest.c | 4 | ||||
| -rw-r--r-- | test/dlopen/nodelete.c | 205 | ||||
| -rw-r--r-- | test/dlopen/nodelmod1.c | 10 | ||||
| -rw-r--r-- | test/dlopen/nodelmod2.c | 10 | ||||
| -rw-r--r-- | test/dlopen/nodelmod3.c | 8 | ||||
| -rw-r--r-- | test/dlopen/nodelmod4.c | 10 | ||||
| -rw-r--r-- | test/dlopen/testscope.c | 29 | ||||
| -rw-r--r-- | test/dlopen/tst-origin.c | 37 |
14 files changed, 441 insertions, 40 deletions
diff --git a/test/dlopen/Makefile b/test/dlopen/Makefile index b59c3e2d2..d5be53c6a 100644 --- a/test/dlopen/Makefile +++ b/test/dlopen/Makefile @@ -1,40 +1,8 @@ # uClibc dlopen tests # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. -# rules need a little love to work with glibc ... -export UCLIBC_ONLY := 1 - -TESTS := dltest dltest2 dlstatic test1 test2 test3 dlundef dlafk dladdr - +top_builddir=../../ +top_srcdir=../../ +include ../Rules.mak +-include Makefile.in include ../Test.mak - -CFLAGS_dltest := -DLIBNAME="\"./libtest.so\"" -CFLAGS_dltest2 := -DLIBNAME="\"./libtest3.so\"" - -LDFLAGS_dlstatic := -ldl -LDFLAGS_dltest := -ldl -lpthread -LDFLAGS_dltest2 := -ldl -lpthread -LDFLAGS_dlundef := -ldl -LDFLAGS_dlafk := -ldl ./libafk.so -Wl,-rpath,. -LDFLAGS_test1 := -ldl -LDFLAGS_test2 := -ldl -LDFLAGS_test3 := -ldl ./libtest1.so ./libtest2.so -Wl,-rpath,. -LDFLAGS_dladdr := -ldl - -DEBUG_LIBS := X -WRAPPER := env $(DEBUG_LIBS)=all LD_LIBRARY_PATH="$$PWD:.:$(LD_LIBRARY_PATH)" - -dltest: libtest.so -dltest2: libtest3.so -dlstatic: libstatic.so -dlundef: libundef.so -dlafk: libafk.so -libafk.so: libafk-temp.so -LDFLAGS_libafk.so := ./libafk-temp.so -Wl,-rpath,. -test1: libtest1.so -test2: libtest1.so libtest2.so -test3: libtest1.so libtest2.so -libtest1.so: libtest2.so -LDFLAGS_libtest1.so := ./libtest2.so -Wl,-rpath,. -LDFLAGS_libtest2.so := -Wl,-rpath,. -LDFLAGS_libtest3.so := -lpthread -Wl,-rpath,. diff --git a/test/dlopen/Makefile.in b/test/dlopen/Makefile.in new file mode 100644 index 000000000..0bed0f749 --- /dev/null +++ b/test/dlopen/Makefile.in @@ -0,0 +1,82 @@ +# uClibc dlopen tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +# rules need a little love to work with glibc ... +export UCLIBC_ONLY := 1 + +TESTS := dltest dltest2 dlstatic test1 test2 test3 dlundef dlafk dladdr \ + testscope nodelete tst-origin + +ifneq ($(HAVE_SHARED),y) +TESTS_DISABLED := test3 +LDFLAGS_libtest.so := -lpthread +endif + +CFLAGS_dltest := -DLIBNAME="\"./libtest.so\"" +CFLAGS_dltest2 := -DLIBNAME="\"./libtest3.so\"" + +LDFLAGS_dlstatic := -ldl +LDFLAGS_dltest := -ldl +LDFLAGS_dltest2 := -ldl +LDFLAGS_dlundef := -ldl +LDFLAGS_dlafk := -ldl ./libafk.so -Wl,-rpath,. +LDFLAGS_test1 := -ldl +LDFLAGS_test2 := -ldl +LDFLAGS_test3 := -ldl ./libtest1.so ./libtest2.so -Wl,-rpath,. +LDFLAGS_dladdr := -ldl +LDFLAGS_testscope:= -ldl +LDFLAGS_tst-origin:= -ldl -Wl,-rpath,\$$ORIGIN/testlib + +DEBUG_LIBS := X +WRAPPER := env $(DEBUG_LIBS)=all LD_LIBRARY_PATH="$$PWD:.:$(LD_LIBRARY_PATH)" + +testlib: + @mkdir $@ + +testlib/libtest31.so: libtest3.so | testlib + @cp $^ $@ + +EXTRA_DIRS := testlib + +# Build libC.so without -mprefergot compilation flag to force a +# R_SH_JMP_SLOT relocation instead of R_SH_GLOB_DAT for _libC_fini. This is +# needed to resolve the _libC_fini symbol when used (by libC.so destructor), +# whereas with GLOB_DAT relocation the resolution happens in the GOT entry +# when the libC is loaded, for the same reason remove also the "-z now" +# linker flag. +# These are needed to spot the issue test case want raise. + +ifeq ($(TARGET_ARCH),sh) +CFLAGS-OMIT-libC.c = -mprefergot +endif +LDFLAGS-OMIT-libC.c = -Wl,-z,now + +dltest: libtest.so +dltest2: libtest3.so +dlstatic: libstatic.so +dlundef: libundef.so +dlafk: libafk.so +testscope:libA.so +libafk.so: libafk-temp.so +LDFLAGS_libafk.so := ./libafk-temp.so -Wl,-rpath,. +test1: libtest1.so +test2: libtest1.so libtest2.so +test3: libtest1.so libtest2.so +tst-origin: testlib/libtest31.so +libtest1.so: libtest2.so +libB.so: libC.so +libA.so: libB.so +LDFLAGS_libtest.so := -lpthread +LDFLAGS_libtest1.so := ./libtest2.so -Wl,-rpath,. +LDFLAGS_libtest2.so := -Wl,-rpath,. +LDFLAGS_libtest3.so := -lpthread -Wl,-rpath,. +LDFLAGS_libC.so := -ldl +LDFLAGS_libB.so := ./libC.so -Wl,-rpath,. +LDFLAGS_libA.so := ./libB.so -Wl,-rpath,. + +nodelete: nodelmod1.so nodelmod2.so nodelmod3.so +nodelmod3.so: nodelmod4.so +LDFLAGS_nodelete := -rdynamic -ldl +LDFLAGS_nodelmod1.so := -Wl,-z,nodelete +LDFLAGS_nodelmod3.so := ./nodelmod4.so +LDFLAGS_nodelmod4.so := -Wl,-z,nodelete diff --git a/test/dlopen/dltest.c b/test/dlopen/dltest.c index 6bec6e00e..b5fa1cdd7 100644 --- a/test/dlopen/dltest.c +++ b/test/dlopen/dltest.c @@ -25,7 +25,7 @@ int main(int argc, char **argv) } mydltest(&value1, &value2); - printf("dltest: __pthread_once=%p\n", value1); + printf("dltest: pthread_once=%p\n", value1); printf("dltest: pthread_self=%p\n", value2); if (value1 == value2) { ret = EXIT_FAILURE; diff --git a/test/dlopen/libA.c b/test/dlopen/libA.c new file mode 100644 index 000000000..13b83dcec --- /dev/null +++ b/test/dlopen/libA.c @@ -0,0 +1,7 @@ +extern void libB_func(void); + +void libA_func(void); +void libA_func(void) +{ + libB_func(); +} diff --git a/test/dlopen/libB.c b/test/dlopen/libB.c new file mode 100644 index 000000000..9b9fff41c --- /dev/null +++ b/test/dlopen/libB.c @@ -0,0 +1,7 @@ +extern void libC_func(void); + +void libB_func(void); +void libB_func(void) +{ + libC_func(); +} diff --git a/test/dlopen/libC.c b/test/dlopen/libC.c new file mode 100644 index 000000000..84cbbef3d --- /dev/null +++ b/test/dlopen/libC.c @@ -0,0 +1,30 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +#define LIBNAME "libB.so" +void _libC_fini(void); +void _libC_fini(void) +{ + printf("libC_fini():finish - atexit()\n"); +} + +void libC_fini(void); +void libC_fini(void) +{ + _libC_fini(); +} + +void libC_func(void); +void libC_func(void) +{ + void *libB; + + libB = dlopen(LIBNAME, RTLD_LAZY); + if (!libB) { + fprintf(stderr, "Could not open ./%s: %s\n", LIBNAME, dlerror()); + exit(1); + } + + atexit(libC_fini); +} diff --git a/test/dlopen/libtest.c b/test/dlopen/libtest.c index a306e4bf7..3fd137f06 100644 --- a/test/dlopen/libtest.c +++ b/test/dlopen/libtest.c @@ -2,12 +2,10 @@ #include <pthread.h> #include <stdint.h> -extern int __pthread_once(void); - void dltest(uint32_t **value1, uint32_t **value2); void dltest(uint32_t **value1, uint32_t **value2) { - *value1 = (uint32_t *) __pthread_once; + *value1 = (uint32_t *) pthread_once; *value2 = (uint32_t *) pthread_self; } diff --git a/test/dlopen/nodelete.c b/test/dlopen/nodelete.c new file mode 100644 index 000000000..07ff96136 --- /dev/null +++ b/test/dlopen/nodelete.c @@ -0,0 +1,205 @@ +#include <dlfcn.h> +#include <setjmp.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> + + +static sigjmp_buf jmpbuf; + + +int fini_ran; + + +static void +__attribute__ ((noreturn)) +handler (int sig) +{ + siglongjmp (jmpbuf, 1); +} + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ + /* We are testing the two possibilities to mark an object as not deletable: + - marked on the linker commandline with `-z nodelete' + - with the RTLD_NODELETE flag at dlopen()-time. + + The test we are performing should be safe. We are loading the objects, + get the address of variables in the respective object, unload the object + and then try to read the variable. If the object is unloaded this + should lead to an segmentation fault. */ + void *p; + struct sigaction sa; + + sa.sa_handler = handler; + sigfillset (&sa.sa_mask); + sa.sa_flags = SA_RESTART; + + if (sigaction (SIGSEGV, &sa, NULL) == -1) + puts ("cannot install signal handler: %m"); + + p = dlopen ("nodelmod1.so", RTLD_LAZY); + if (p == NULL) + { + printf ("failed to load \"nodelmod1.so\": %s\n", dlerror ()); + exit (1); + } + else + { + int *varp; + + varp = dlsym (p, "var1"); + if (varp == NULL) + { + puts ("failed to get address of \"var1\" in \"nodelmod1.so\""); + exit (1); + } + else + { + *varp = 20000720; + + /* Now close the object. */ + fini_ran = 0; + if (dlclose (p) != 0) + { + puts ("failed to close \"nodelmod1.so\""); + exit (1); + } + else if (! sigsetjmp (jmpbuf, 1)) + { + /* Access the variable again. */ + if (*varp != 20000720) + { + puts ("\"var1\" value not correct"); + exit (1); + } + else if (fini_ran != 0) + { + puts ("destructor of \"nodelmod1.so\" ran"); + exit (1); + } + else + puts ("-z nodelete test succeeded"); + } + else + { + /* We caught an segmentation fault. */ + puts ("\"nodelmod1.so\" got deleted!"); + exit (1); + } + } + } + + p = dlopen ("nodelmod2.so", RTLD_LAZY | RTLD_NODELETE); + if (p == NULL) + { + printf ("failed to load \"nodelmod2.so\": %s\n", dlerror ()); + exit (1); + } + else + { + int *varp; + + varp = dlsym (p, "var2"); + if (varp == NULL) + { + puts ("failed to get address of \"var2\" in \"nodelmod2.so\""); + exit (1); + } + else + { + *varp = 42; + + /* Now close the object. */ + fini_ran = 0; + if (dlclose (p) != 0) + { + puts ("failed to close \"nodelmod2.so\""); + exit (1); + } + else if (! sigsetjmp (jmpbuf, 1)) + { + /* Access the variable again. */ + if (*varp != 42) + { + puts ("\"var2\" value not correct"); + exit (1); + } + else if (fini_ran != 0) + { + puts ("destructor of \"nodelmod2.so\" ran"); + exit (1); + } + else + puts ("RTLD_NODELETE test succeeded"); + } + else + { + /* We caught an segmentation fault. */ + puts ("\"nodelmod2.so\" got deleted!"); + exit (1); + } + } + } + + p = dlopen ("nodelmod3.so", RTLD_LAZY); + if (p == NULL) + { + printf ("failed to load \"nodelmod3.so\": %s\n", dlerror ()); + exit (1); + } + else + { + int *(*fctp) (void); + + fctp = dlsym (p, "addr"); + if (fctp == NULL) + { + puts ("failed to get address of \"addr\" in \"nodelmod3.so\""); + exit (1); + } + else + { + int *varp = fctp (); + + *varp = -1; + + /* Now close the object. */ + fini_ran = 0; + if (dlclose (p) != 0) + { + puts ("failed to close \"nodelmod3.so\""); + exit (1); + } + else if (! sigsetjmp (jmpbuf, 1)) + { + /* Access the variable again. */ + if (*varp != -1) + { + puts ("\"var_in_mod4\" value not correct"); + exit (1); + } + else if (fini_ran != 0) + { + puts ("destructor of \"nodelmod4.so\" ran"); + exit (1); + } + else + puts ("-z nodelete in dependency succeeded"); + } + else + { + /* We caught an segmentation fault. */ + puts ("\"nodelmod4.so\" got deleted!"); + exit (1); + } + } + } + + return 0; +} + +#include "../test-skeleton.c" diff --git a/test/dlopen/nodelmod1.c b/test/dlopen/nodelmod1.c new file mode 100644 index 000000000..51be080af --- /dev/null +++ b/test/dlopen/nodelmod1.c @@ -0,0 +1,10 @@ +extern int fini_ran; + +int var1 = 42; + +static void +__attribute__ ((__destructor__)) +destr (void) +{ + fini_ran = 1; +} diff --git a/test/dlopen/nodelmod2.c b/test/dlopen/nodelmod2.c new file mode 100644 index 000000000..ff2ffc2fc --- /dev/null +++ b/test/dlopen/nodelmod2.c @@ -0,0 +1,10 @@ +extern int fini_ran; + +int var2 = 100; + +static void +__attribute__ ((__destructor__)) +destr (void) +{ + fini_ran = 1; +} diff --git a/test/dlopen/nodelmod3.c b/test/dlopen/nodelmod3.c new file mode 100644 index 000000000..817c94db6 --- /dev/null +++ b/test/dlopen/nodelmod3.c @@ -0,0 +1,8 @@ +extern int var_in_mod4; +extern int *addr (void); + +int * +addr (void) +{ + return &var_in_mod4; +} diff --git a/test/dlopen/nodelmod4.c b/test/dlopen/nodelmod4.c new file mode 100644 index 000000000..d7fa89396 --- /dev/null +++ b/test/dlopen/nodelmod4.c @@ -0,0 +1,10 @@ +extern int fini_ran; + +int var_in_mod4 = 99; + +static void +__attribute__ ((__destructor__)) +destr (void) +{ + fini_ran = 1; +} diff --git a/test/dlopen/testscope.c b/test/dlopen/testscope.c new file mode 100644 index 000000000..90e079885 --- /dev/null +++ b/test/dlopen/testscope.c @@ -0,0 +1,29 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +#define LIBNAME "libA.so" +int main(int argc, char **argv) +{ + void *libA; + void (*libAfn)(void); + char *error; + + libA = dlopen(LIBNAME, RTLD_LAZY); + if (!libA) { + fprintf(stderr, "Could not open ./%s: %s\n", LIBNAME, dlerror()); + exit(1); + } + + libAfn = dlsym(libA, "libA_func"); + if ((error = dlerror()) != NULL) { + fprintf(stderr, "Could not locate symbol 'libA_func': %s\n", error); + exit(1); + } + + libAfn(); + + dlclose(libA); + + return EXIT_SUCCESS; +} diff --git a/test/dlopen/tst-origin.c b/test/dlopen/tst-origin.c new file mode 100644 index 000000000..a12be415b --- /dev/null +++ b/test/dlopen/tst-origin.c @@ -0,0 +1,37 @@ +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <dlfcn.h> + +#ifdef __UCLIBC__ +extern void _dlinfo(void); +#endif + +int main(int argc, char **argv) { + void *h1, *h2; + int (*mydltest)(const char *s); + char *error; + + h1 = dlopen ("libtest31.so", RTLD_LAZY); + if (!h1) { + fprintf(stderr, "Could not open libtest31.so: %s\n", dlerror()); + exit(1); + } + + h2 = dlopen ("libtest31.so", RTLD_NOLOAD); + if (!h2) { + fprintf(stderr, "Could not open libtest31.so(RTLD_NOLOAD): %s\n", dlerror()); + exit(1); + } + + mydltest = dlsym(h1, "dltest"); + if ((error = dlerror()) != NULL) { + fprintf(stderr, "Could not locate symbol 'dltest': %s\n", error); + exit(1); + } + + dlclose(h2); + dlclose(h1); + + return EXIT_SUCCESS; +} |
