summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippo ARCIDIACONO <filippo.arcidiacono@st.com>2012-01-23 17:01:58 +0100
committerCarmelo Amoroso <carmelo.amoroso@st.com>2012-02-07 17:11:47 +0100
commitac33828db194ddd8dc112439cf0d1d935e4e1452 (patch)
tree30ed7a63a428c242c4036c586c61b26eef0a0af1
parentcf068ce38bc17230fd60adb10b4cf70ead7e7cd0 (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.in23
-rw-r--r--test/dlopen/libA.c7
-rw-r--r--test/dlopen/libB.c7
-rw-r--r--test/dlopen/libC.c30
-rw-r--r--test/dlopen/testscope.c29
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;
+}