summaryrefslogtreecommitdiff
path: root/test/dlopen
diff options
context:
space:
mode:
Diffstat (limited to 'test/dlopen')
-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;
+}