summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2010-10-20 21:38:34 +0200
committerDavid 'Digit' Turner <digit@google.com>2010-10-21 03:27:34 +0200
commit133a37ede3e955093c6004d94496e2cdc2cc1264 (patch)
tree7a2c633c887098b761874b16f54da1f98bbbbbc5
parent91ad0fe2d060598735fd1cbd2cff10fff4aa76ce (diff)
downloadextras-133a37ede3e955093c6004d94496e2cdc2cc1264.tar.gz
tests: Refine Bionic dlclose destruction test.
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
-rw-r--r--tests/bionic/libc/Android.mk38
-rw-r--r--tests/bionic/libc/bionic/libdlclosetest2.c73
-rw-r--r--tests/bionic/libc/bionic/test_dlclose_destruction.c35
-rw-r--r--tests/bionic/libc/common/test_clone.c29
-rw-r--r--tests/bionic/libc/common/test_executable_destructor.c104
-rw-r--r--tests/bionic/libc/common/test_gethostbyname.c28
-rw-r--r--tests/bionic/libc/common/test_gethostname.c27
7 files changed, 317 insertions, 17 deletions
diff --git a/tests/bionic/libc/Android.mk b/tests/bionic/libc/Android.mk
index 932d385e..3f25ccb7 100644
--- a/tests/bionic/libc/Android.mk
+++ b/tests/bionic/libc/Android.mk
@@ -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
index 00000000..bd37175a
--- /dev/null
+++ b/tests/bionic/libc/bionic/libdlclosetest2.c
@@ -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);
+}
diff --git a/tests/bionic/libc/bionic/test_dlclose_destruction.c b/tests/bionic/libc/bionic/test_dlclose_destruction.c
index fac6a867..928057a1 100644
--- a/tests/bionic/libc/bionic/test_dlclose_destruction.c
+++ b/tests/bionic/libc/bionic/test_dlclose_destruction.c
@@ -35,34 +35,35 @@
#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;
}
diff --git a/tests/bionic/libc/common/test_clone.c b/tests/bionic/libc/common/test_clone.c
index afbb9c17..bb313e8f 100644
--- a/tests/bionic/libc/common/test_clone.c
+++ b/tests/bionic/libc/common/test_clone.c
@@ -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
index 00000000..e0e1d454
--- /dev/null
+++ b/tests/bionic/libc/common/test_executable_destructor.c
@@ -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;
+}
diff --git a/tests/bionic/libc/common/test_gethostbyname.c b/tests/bionic/libc/common/test_gethostbyname.c
index 1e932d60..90b185df 100644
--- a/tests/bionic/libc/common/test_gethostbyname.c
+++ b/tests/bionic/libc/common/test_gethostbyname.c
@@ -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>
diff --git a/tests/bionic/libc/common/test_gethostname.c b/tests/bionic/libc/common/test_gethostname.c
index b9dcbafc..96ca4e32 100644
--- a/tests/bionic/libc/common/test_gethostname.c
+++ b/tests/bionic/libc/common/test_gethostname.c
@@ -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>