[git commit] tests:libdl: add a new test for symbol scope issue in dlclose

Carmelo Amoroso carmelo.amoroso at st.com
Tue Feb 7 16:11:47 UTC 2012


commit: http://git.uclibc.org/uClibc/commit/?id=ac33828db194ddd8dc112439cf0d1d935e4e1452
branch: http://git.uclibc.org/uClibc/commit/?id=refs/heads/master

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 at st.com>
Signed-off-by: Carmelo Amoroso <carmelo.amoroso at st.com>
Reported-by: Khem Raj <raj.khem at gmail.com>
---
 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 deletions(-)

diff --git a/test/dlopen/Makefile.in b/test/dlopen/Makefile.in
index 22190d9..9b4af35 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 0000000..13b83dc
--- /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 0000000..9b9fff4
--- /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 0000000..84cbbef
--- /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 0000000..90e0798
--- /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;
+}


More information about the uClibc-cvs mailing list