OSDN Git Service

tests: Refine Bionic dlclose destruction test.
authorDavid 'Digit' Turner <digit@google.com>
Wed, 20 Oct 2010 19:38:34 +0000 (21:38 +0200)
committerDavid 'Digit' Turner <digit@google.com>
Thu, 21 Oct 2010 01:27:34 +0000 (03:27 +0200)
The purpose of this change is to test that C constructors and
destructors contained in shared libraries are properly called
when the corresponding libs are loaded and unloaded through
dlopen() and dlclose(), or when the program exits.

The test_dlclose_destruction test already performs this for
static C++ construction/destruction. The change refines it
with another shared library that uses __attribute__((constructor))
and __attribute__((destructor)) from C instead

(see the new libdlclosetest2 shared library).

A new test, test_executable_destructor is also added to check
that the constructor and destructor functions located in the
executable program itself are properly called.

Change-Id: If364d1c710282e8117f980b09490770e7d8d1e33

tests/bionic/libc/Android.mk
tests/bionic/libc/bionic/libdlclosetest2.c [new file with mode: 0644]
tests/bionic/libc/bionic/test_dlclose_destruction.c
tests/bionic/libc/common/test_clone.c
tests/bionic/libc/common/test_executable_destructor.c [new file with mode: 0644]
tests/bionic/libc/common/test_gethostbyname.c
tests/bionic/libc/common/test_gethostname.c

index 932d385..3f25ccb 100644 (file)
@@ -61,6 +61,7 @@ endef
 # First, the tests in 'common'
 
 sources := \
+    common/test_executable_destructor.c \
     common/test_getaddrinfo.c \
     common/test_gethostbyname.c \
     common/test_gethostname.c \
@@ -85,6 +86,24 @@ EXTRA_CFLAGS := -D_XOPEN_SOURCE=600 -DHOST
 $(call host-test, $(sources))
 $(call device-test, $(sources))
 
+# The 'test_static_executable_destructor is the same than
+# test_executable_destructor except that the generated program
+# is statically linked instead.
+include $(CLEAR_VARS)
+LOCAL_MODULE := test_static_executable_destructor
+LOCAL_SRC_FILES := common/test_executable_destructor.c
+LOCAL_MODULE_TAGS := tests
+LOCAL_STATIC_LIBRARIES := libc
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := test_static_executable_destructor
+LOCAL_SRC_FILES := common/test_executable_destructor.c
+LOCAL_MODULE_TAGS := tests
+LOCAL_LDFLAGS := -static
+include $(BUILD_HOST_EXECUTABLE)
+
 # The 'test_dlopen_null' tests requires specific linker flags
 #
 # The -Wl,--export-dynamic ensures that dynamic symbols are
@@ -149,12 +168,14 @@ include $(CLEAR_VARS)
 LOCAL_SRC_FILES := bionic/lib_relocs.c
 LOCAL_MODULE    := libtest_relocs
 LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_TAGS := tests
 include $(BUILD_SHARED_LIBRARY)
 
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := bionic/test_relocs.c
 LOCAL_MODULE    := test_relocs
 LOCAL_SHARED_LIBRARIES := libtest_relocs
+LOCAL_MODULE_TAGS := tests
 include $(BUILD_EXECUTABLE)
 
 # This test tries to see if the static constructors in a
@@ -166,12 +187,14 @@ include $(CLEAR_VARS)
 LOCAL_SRC_FILES := bionic/lib_static_init.cpp
 LOCAL_MODULE    := libtest_static_init
 LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_TAGS := tests
 include $(BUILD_SHARED_LIBRARY)
 
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := bionic/test_static_init.cpp
 LOCAL_MODULE    := test_static_init
 LOCAL_SHARED_LIBRARIES := libtest_static_init
+LOCAL_MODULE_TAGS := tests
 include $(BUILD_EXECUTABLE)
 
 # This test tries to see if static destructors are called
@@ -180,25 +203,38 @@ include $(CLEAR_VARS)
 LOCAL_SRC_FILES := bionic/libdlclosetest1.cpp
 LOCAL_MODULE := libdlclosetest1
 LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_TAGS := tests
+include $(BUILD_SHARED_LIBRARY)
+
+# And this one does the same with __attribute__((constructor))
+# and __attribute__((destructor))
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := bionic/libdlclosetest2.c
+LOCAL_MODULE := libdlclosetest2
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_TAGS := tests
 include $(BUILD_SHARED_LIBRARY)
 
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := bionic/test_dlclose_destruction.c
 LOCAL_MODULE := test_dlclose_destruction
 LOCAL_LDFLAGS := -ldl
-#LOCAL_SHARED_LIBRARIES := libdlclosetest1
+#LOCAL_SHARED_LIBRARIES := libdlclosetest1 libdlclosetest2
+LOCAL_MODULE_TAGS := tests
 include $(BUILD_EXECUTABLE)
 
 # Testing 'clone' is only possible on Linux systems
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := common/test_clone.c
 LOCAL_MODULE := test_clone
+LOCAL_MODULE_TAGS := tests
 include $(BUILD_EXECUTABLE)
 
 ifeq ($(HOST_OS),linux)
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := common/test_clone.c
 LOCAL_MODULE := test_clone
+LOCAL_MODULE_TAGS := tests
 include $(BUILD_HOST_EXECUTABLE)
 endif
 
diff --git a/tests/bionic/libc/bionic/libdlclosetest2.c b/tests/bionic/libc/bionic/libdlclosetest2.c
new file mode 100644 (file)
index 0000000..bd37175
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+/* This library is used to ensure that static C construction
+ * and destruction operate normally on dlopen() and dlclose().
+ *
+ * We use a global variable inside the DLL called "x"
+ * and initialize it to 1 in the static Foo_create constructor.
+ *
+ * The main program can access its address through dlsym()
+ * then later check that it was properly initialized.
+ */
+int x = 0;
+
+static void __attribute__((constructor))
+Foo_create(void)
+{
+    x = 1;
+    fprintf(stderr, "%s: setting x to 1\n", __FUNCTION__);
+}
+
+/* Similarly, the main program can provide the address of
+ * an integer, named "y", that will be set to 2 when the
+ * destructor is called on dlclose().
+ *
+ * This address must be provided through the "set_y" function
+ * that can also be resolved through dlsym() by the program.
+ */
+static int *to_y = NULL;
+
+static void __attribute__((destructor))
+Foo_destroy(void)
+{
+    if (to_y == NULL) {
+        fprintf(stderr, "%s: to_y uninitialized!!\n", __FUNCTION__);
+        *(int *)NULL = 0; // crash
+    }
+    *to_y = 2;
+    fprintf(stderr, "%s: setting y(%p) to 2!\n", __FUNCTION__, to_y);
+}
+
+void set_y(int *y)
+{
+    to_y = y;
+    fprintf(stderr, "%s: setting to_y=%p\n", __FUNCTION__, y);
+}
index fac6a86..928057a 100644 (file)
 #include <dlfcn.h>
 #include <stdio.h>
 
-int main(void)
+static int
+check_library(const char*  libname)
 {
-    void*  lib = dlopen("libdlclosetest1.so", RTLD_NOW);
+    void*  lib = dlopen(libname, RTLD_NOW);
     int*   to_x;
     void  (*set_y)(int *);
     int    y = 0;
 
     if (lib == NULL) {
-        fprintf(stderr, "Could not load shared library: %s\n", dlerror());
+        fprintf(stderr, "Could not load shared library %s: %s\n", libname, dlerror());
         return 1;
     }
 
-    fprintf(stderr, "Loaded !!\n");
+    fprintf(stderr, "%s loaded.\n", libname);
 
     to_x = dlsym(lib, "x");
-    if (to_x == NULL) { 
-        fprintf(stderr, "Could not access global DLL variable (x): %s\n", dlerror());
+    if (to_x == NULL) {
+        fprintf(stderr, "Could not access global DLL variable (x) in %s: %s\n", libname, dlerror());
         return 10;
     }
 
     if (*to_x != 1) {
-        fprintf(stderr, "Static C++ constructor was not run on dlopen() !\n");
+        fprintf(stderr, "Constructor was not run on dlopen(\"%s\") !\n", libname);
         return 11;
     }
 
     set_y = dlsym(lib, "set_y");
     if (set_y == NULL) {
-        fprintf(stderr, "Could not access global DLL function (set_y): %s\n", dlerror());
+        fprintf(stderr, "Could not access global DLL function (set_y) in %s: %s\n", libname, dlerror());
         return 12;
     }
 
@@ -70,16 +71,20 @@ int main(void)
     (*set_y)(&y);
 
     if (dlclose(lib) < 0) {
-        fprintf(stderr, "Could not unload shared library: %s\n", dlerror());
+        fprintf(stderr, "Could not unload shared library %s: %s\n", libname, dlerror());
         return 2;
     }
 
-    fprintf(stderr, "Unloaded !!\n");
-
-    if (y != 2) {
-        fprintf(stderr, "Static C++ destructor was not run on dlclose() !\n");
-        return 11;
-    }
+    fprintf(stderr, "%s unloaded.\n", libname);
+    return 0;
+}
 
+int main(void)
+{
+    /* Testing static C++ construction/destruction */
+    if (check_library("libdlclosetest1.so"))
+        return 1;
+    if (check_library("libdlclosetest2.so"))
+        return 2;
     return 0;
 }
index afbb9c1..bb313e8 100644 (file)
@@ -1,6 +1,33 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 /* Check that clone() is implemented and properly works
  */
-#define __GNU_SOURCE 1
+#define _GNU_SOURCE 1
 #include <stdio.h>
 #include <errno.h>
 #include <sched.h>
diff --git a/tests/bionic/libc/common/test_executable_destructor.c b/tests/bionic/libc/common/test_executable_destructor.c
new file mode 100644 (file)
index 0000000..e0e1d45
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+
+/* A very simple program used to test constructor and destructor functions
+ * in executables (instead of shared libraries).
+ */
+
+int x = 0;
+
+/* Initialize x to 1 when the program starts. This will be checked
+ * later by the main() function.
+ */
+static void __attribute__((constructor))
+on_load(void)
+{
+    x = 1;
+}
+
+/* Crash intentionally if 'x' is set to 1 */
+static void __attribute__((destructor))
+on_exit(void)
+{
+    if (x == 1)
+        *(int*)(void*)0 = 10;  /* force a crash */
+}
+
+int main(void)
+{
+    int status;
+    pid_t pid;
+
+    /* First, check that the constructor was properly called ! */
+    if (x != 1) {
+        fprintf(stderr, "Constructor function not called!!\n");
+        return 1;
+    }
+
+    /* prevent our crashing child process from generating a core file */
+    {
+        struct rlimit rlim;
+        rlim.rlim_cur = 0;
+        rlim.rlim_max = RLIM_INFINITY;
+        setrlimit(RLIMIT_CORE, &rlim);
+    }
+
+    /* Fork the current process, then wait for the child to exit
+     * and crash.
+     */
+    pid = fork();
+    if (pid < 0) {
+        fprintf(stderr, "Could not fork process: %s\n", strerror(errno));
+        return 2;
+    }
+    /* in the child, simply exit after 1 second. */
+    if (pid == 0) {
+        sleep(1);
+        return 0;
+    }
+    /* in the parent, wait for the child to terminate */
+    if (wait(&status) < 0) {
+        fprintf(stderr, "Could not wait for child: %s\n", strerror(errno));
+        return 3;
+    }
+    if (!WIFSIGNALED(status)) {
+        fprintf(stderr, "Destructor not called!!\n");
+        return 4;
+    }
+
+    /* Prevent crashing */
+    x = 2;
+    printf("ok\n");
+    return 0;
+}
index 1e932d6..90b185d 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#define _GNU_SOURCE 1
 #include <unistd.h>
 #include <errno.h>
 #include <string.h>
index b9dcbaf..96ca4e3 100644 (file)
@@ -1,3 +1,30 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 #include <unistd.h>
 #include <errno.h>
 #include <string.h>