diff options
author | David 'Digit' Turner <digit@google.com> | 2010-10-20 21:38:34 +0200 |
---|---|---|
committer | David 'Digit' Turner <digit@google.com> | 2010-10-21 03:27:34 +0200 |
commit | 133a37ede3e955093c6004d94496e2cdc2cc1264 (patch) | |
tree | 7a2c633c887098b761874b16f54da1f98bbbbbc5 | |
parent | 91ad0fe2d060598735fd1cbd2cff10fff4aa76ce (diff) | |
download | extras-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.mk | 38 | ||||
-rw-r--r-- | tests/bionic/libc/bionic/libdlclosetest2.c | 73 | ||||
-rw-r--r-- | tests/bionic/libc/bionic/test_dlclose_destruction.c | 35 | ||||
-rw-r--r-- | tests/bionic/libc/common/test_clone.c | 29 | ||||
-rw-r--r-- | tests/bionic/libc/common/test_executable_destructor.c | 104 | ||||
-rw-r--r-- | tests/bionic/libc/common/test_gethostbyname.c | 28 | ||||
-rw-r--r-- | tests/bionic/libc/common/test_gethostname.c | 27 |
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> |