From ac33828db194ddd8dc112439cf0d1d935e4e1452 Mon Sep 17 00:00:00 2001 From: Filippo ARCIDIACONO Date: Mon, 23 Jan 2012 17:01:58 +0100 Subject: 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 Signed-off-by: Carmelo Amoroso Reported-by: Khem Raj --- test/dlopen/Makefile.in | 23 ++++++++++++++++++++++- test/dlopen/libA.c | 7 +++++++ test/dlopen/libB.c | 7 +++++++ test/dlopen/libC.c | 30 ++++++++++++++++++++++++++++++ test/dlopen/testscope.c | 29 +++++++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 test/dlopen/libA.c create mode 100644 test/dlopen/libB.c create mode 100644 test/dlopen/libC.c create mode 100644 test/dlopen/testscope.c (limited to 'test') 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 +#include +#include + +#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 +#include +#include + +#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; +} -- cgit v1.2.3