diff options
author | Filippo ARCIDIACONO <filippo.arcidiacono@st.com> | 2012-01-23 17:01:58 +0100 |
---|---|---|
committer | Carmelo Amoroso <carmelo.amoroso@st.com> | 2012-02-07 17:11:47 +0100 |
commit | ac33828db194ddd8dc112439cf0d1d935e4e1452 (patch) | |
tree | 30ed7a63a428c242c4036c586c61b26eef0a0af1 | |
parent | cf068ce38bc17230fd60adb10b4cf70ead7e7cd0 (diff) |
tests:libdl: add a new test for symbol scope issue in dlclose
Test case to trigger an issue raised by the new symbol scope design,
that was erroneously removing local symbol scope from the global one
too early while dl-closing a shared library.
Based on original test-case by Khem Raj
Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono@st.com>
Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
Reported-by: Khem Raj <raj.khem@gmail.com>
-rw-r--r-- | test/dlopen/Makefile.in | 23 | ||||
-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/testscope.c | 29 |
5 files changed, 95 insertions, 1 deletions
diff --git a/test/dlopen/Makefile.in b/test/dlopen/Makefile.in index 22190d9f9..9b4af35e4 100644 --- a/test/dlopen/Makefile.in +++ b/test/dlopen/Makefile.in @@ -4,7 +4,8 @@ # rules need a little love to work with glibc ... export UCLIBC_ONLY := 1 -TESTS := dltest dltest2 dlstatic test1 test2 test3 dlundef dlafk dladdr +TESTS := dltest dltest2 dlstatic test1 test2 test3 dlundef dlafk dladdr \ + testscope CFLAGS_dltest := -DLIBNAME="\"./libtest.so\"" CFLAGS_dltest2 := -DLIBNAME="\"./libtest3.so\"" @@ -18,22 +19,42 @@ LDFLAGS_test1 := -ldl LDFLAGS_test2 := -ldl LDFLAGS_test3 := -ldl ./libtest1.so ./libtest2.so -Wl,-rpath,. LDFLAGS_dladdr := -ldl +LDFLAGS_testscope:= -ldl DEBUG_LIBS := X WRAPPER := env $(DEBUG_LIBS)=all LD_LIBRARY_PATH="$$PWD:.:$(LD_LIBRARY_PATH)" +# 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 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,. 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/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; +} |