diff options
author | Alexey Samsonov <samsonov@google.com> | 2014-04-01 13:16:30 +0000 |
---|---|---|
committer | Alexey Samsonov <samsonov@google.com> | 2014-04-01 13:16:30 +0000 |
commit | d6535ea4c4d49078a93735b315b8518fb692a592 (patch) | |
tree | e114342968d294d188587a94d6dea587a66e3f19 /test/asan | |
parent | f9470a30623dab95050c32e10576d706b13675dd (diff) |
[ASan] Optional support for dynamic ASan runtime on Linux.
Based on http://llvm-reviews.chandlerc.com/D3042 by Yuri Gribov!
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@205308 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/asan')
-rw-r--r-- | test/asan/CMakeLists.txt | 26 | ||||
-rw-r--r-- | test/asan/TestCases/Linux/asan_dlopen_test.cc | 14 | ||||
-rw-r--r-- | test/asan/TestCases/Linux/asan_preload_test-1.cc | 27 | ||||
-rw-r--r-- | test/asan/TestCases/Linux/asan_preload_test-2.cc | 21 | ||||
-rw-r--r-- | test/asan/TestCases/Linux/asan_rt_confict_test-1.cc | 12 | ||||
-rw-r--r-- | test/asan/TestCases/Linux/asan_rt_confict_test-2.cc | 24 | ||||
-rw-r--r-- | test/asan/TestCases/Linux/interface_symbols_linux.c | 2 | ||||
-rw-r--r-- | test/asan/TestCases/sanity_check_pure_c.c | 2 | ||||
-rw-r--r-- | test/asan/Unit/lit.site.cfg.in | 10 | ||||
-rw-r--r-- | test/asan/lit.cfg | 40 | ||||
-rw-r--r-- | test/asan/lit.site.cfg.in | 2 |
11 files changed, 163 insertions, 17 deletions
diff --git a/test/asan/CMakeLists.txt b/test/asan/CMakeLists.txt index 954fc7065..0dd6f816a 100644 --- a/test/asan/CMakeLists.txt +++ b/test/asan/CMakeLists.txt @@ -21,29 +21,47 @@ if(CAN_TARGET_x86_64 OR CAN_TARGET_powerpc64) set(ASAN_TEST_CONFIG_SUFFIX "64") set(ASAN_TEST_BITS "64") set(ASAN_TEST_TARGET_CFLAGS ${TARGET_64_BIT_CFLAGS}) + set(ASAN_TEST_DYNAMIC False) configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/64bitConfig/lit.site.cfg ) list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/64bitConfig) + if(COMPILER_RT_BUILD_SHARED_ASAN) + set(ASAN_TEST_CONFIG_SUFFIX "64-Dynamic") + set(ASAN_TEST_DYNAMIC True) + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/64bitConfig-dynamic/lit.site.cfg) + list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/64bitConfig-dynamic) + endif() endif() if(CAN_TARGET_i386) set(ASAN_TEST_CONFIG_SUFFIX "32") set(ASAN_TEST_BITS "32") set(ASAN_TEST_TARGET_CFLAGS ${TARGET_32_BIT_CFLAGS}) + set(ASAN_TEST_DYNAMIC False) + set(ASAN_TEST_TARGET_ARCH "i386") configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig/lit.site.cfg ) list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig) + if(COMPILER_RT_BUILD_SHARED_ASAN) + set(ASAN_TEST_CONFIG_SUFFIX "32-Dynamic") + set(ASAN_TEST_DYNAMIC True) + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig-dynamic/lit.site.cfg) + list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/32bitConfig-dynamic) + endif() endif() if(COMPILER_RT_INCLUDE_TESTS) -configure_lit_site_cfg( - ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in - ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg - ) + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg) endif() set(ASAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) diff --git a/test/asan/TestCases/Linux/asan_dlopen_test.cc b/test/asan/TestCases/Linux/asan_dlopen_test.cc new file mode 100644 index 000000000..83ce4f83b --- /dev/null +++ b/test/asan/TestCases/Linux/asan_dlopen_test.cc @@ -0,0 +1,14 @@ +// Test that dlopen of dynamic runtime is prohibited. +// +// RUN: %clangxx %s -DRT=\"%shared_libasan\" -o %t -ldl +// RUN: not %t 2>&1 | FileCheck %s +// REQUIRES: asan-dynamic-runtime + +#include <dlfcn.h> + +int main(int argc, char **argv) { + dlopen(RT, RTLD_LAZY); + return 0; +} + +// CHECK: ASan runtime does not come first in initial library list diff --git a/test/asan/TestCases/Linux/asan_preload_test-1.cc b/test/asan/TestCases/Linux/asan_preload_test-1.cc new file mode 100644 index 000000000..f6eff8ee1 --- /dev/null +++ b/test/asan/TestCases/Linux/asan_preload_test-1.cc @@ -0,0 +1,27 @@ +// Test that non-sanitized executables work with sanitized shared libs +// and preloaded runtime. +// +// RUN: %clangxx -DBUILD_SO=1 -fPIC -shared %s -o %t.so +// RUN: %clangxx %s %t.so -o %t +// +// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t.so +// RUN: LD_PRELOAD=%shared_libasan not %t 2>&1 | FileCheck %s + +// REQUIRES: asan-dynamic-runtime + +#if BUILD_SO +char dummy; +void do_access(const void *p) { + // CHECK: AddressSanitizer: heap-buffer-overflow + dummy = ((const char *)p)[1]; +} +#else +#include <stdlib.h> +extern void do_access(const void *p); +int main(int argc, char **argv) { + void *p = malloc(1); + do_access(p); + free(p); + return 0; +} +#endif diff --git a/test/asan/TestCases/Linux/asan_preload_test-2.cc b/test/asan/TestCases/Linux/asan_preload_test-2.cc new file mode 100644 index 000000000..a0f88ce93 --- /dev/null +++ b/test/asan/TestCases/Linux/asan_preload_test-2.cc @@ -0,0 +1,21 @@ +// Test that preloaded runtime works with unsanitized executables. +// +// RUN: %clangxx %s -o %t +// RUN: LD_PRELOAD=%shared_libasan not %t 2>&1 | FileCheck %s + +// REQUIRES: asan-dynamic-runtime + +#include <stdlib.h> + +extern "C" void *memset(void *p, int val, size_t n); + +void do_access(void *p) { + // CHECK: AddressSanitizer: heap-buffer-overflow + memset(p, 0, 2); +} + +int main(int argc, char **argv) { + void *p = malloc(1); + do_access(p); + return 0; +} diff --git a/test/asan/TestCases/Linux/asan_rt_confict_test-1.cc b/test/asan/TestCases/Linux/asan_rt_confict_test-1.cc new file mode 100644 index 000000000..a66aaf2a8 --- /dev/null +++ b/test/asan/TestCases/Linux/asan_rt_confict_test-1.cc @@ -0,0 +1,12 @@ +// Test that preloading dynamic runtime to statically sanitized +// executable is prohibited. +// +// RUN: %clangxx_asan_static %s -o %t +// RUN: LD_PRELOAD=%shared_libasan not %t 2>&1 | FileCheck %s + +// REQUIRES: asan-dynamic-runtime + +#include <stdlib.h> +int main(int argc, char **argv) { return 0; } + +// CHECK: Your application is linked against incompatible ASan runtimes diff --git a/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc b/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc new file mode 100644 index 000000000..3898e7bb1 --- /dev/null +++ b/test/asan/TestCases/Linux/asan_rt_confict_test-2.cc @@ -0,0 +1,24 @@ +// Test that mixed static/dynamic sanitization of program objects +// is prohibited. +// +// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t.so +// RUN: %clangxx_asan_static %s %t.so -o %t +// RUN: not %t 2>&1 | FileCheck %s + +// REQUIRES: asan-dynamic-runtime + +#if BUILD_SO +char dummy; +void do_access(const void *p) { dummy = ((const char *)p)[1]; } +#else +#include <stdlib.h> +extern void do_access(const void *p); +int main(int argc, char **argv) { + void *p = malloc(1); + do_access(p); + free(p); + return 0; +} +#endif + +// CHECK: Your application is linked against incompatible ASan runtimes diff --git a/test/asan/TestCases/Linux/interface_symbols_linux.c b/test/asan/TestCases/Linux/interface_symbols_linux.c index f67a12476..4764ef7f0 100644 --- a/test/asan/TestCases/Linux/interface_symbols_linux.c +++ b/test/asan/TestCases/Linux/interface_symbols_linux.c @@ -31,6 +31,6 @@ // FIXME: nm -D on powerpc somewhy shows ASan interface symbols residing // in "initialized data section". -// REQUIRES: x86_64-supported-target,i386-supported-target +// REQUIRES: x86_64-supported-target,i386-supported-target,asan-static-runtime int main() { return 0; } diff --git a/test/asan/TestCases/sanity_check_pure_c.c b/test/asan/TestCases/sanity_check_pure_c.c index df150675b..6065532a5 100644 --- a/test/asan/TestCases/sanity_check_pure_c.c +++ b/test/asan/TestCases/sanity_check_pure_c.c @@ -3,7 +3,7 @@ // RUN: not %t 2>&1 | FileCheck %s // Sanity checking a test in pure C with -pie. -// RUN: %clang_asan -O2 %s -pie -o %t +// RUN: %clang_asan -O2 %s -pie -fPIE -o %t // RUN: not %t 2>&1 | FileCheck %s #include <stdlib.h> diff --git a/test/asan/Unit/lit.site.cfg.in b/test/asan/Unit/lit.site.cfg.in index 96cfc386a..46eea1ff9 100644 --- a/test/asan/Unit/lit.site.cfg.in +++ b/test/asan/Unit/lit.site.cfg.in @@ -1,9 +1,16 @@ ## Autogenerated by LLVM/Clang configuration. # Do not edit! +import os + # Load common config for all compiler-rt unit tests. lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/unittests/lit.common.unit.configured") +def push_ld_library_path(config, new_path): + new_ld_library_path = os.path.pathsep.join( + (new_path, config.environment['LD_LIBRARY_PATH'])) + config.environment['LD_LIBRARY_PATH'] = new_ld_library_path + # Setup config name. config.name = 'AddressSanitizer-Unit' @@ -13,6 +20,9 @@ config.name = 'AddressSanitizer-Unit' config.test_exec_root = "@COMPILER_RT_BINARY_DIR@/lib/asan/tests" config.test_source_root = config.test_exec_root +# Set LD_LIBRARY_PATH to pick dynamic runtime up properly. +push_ld_library_path(config, config.compiler_rt_libdir) + # Enable leak detection in ASan unit tests on x86_64-linux. if config.host_os == 'Linux' and config.host_arch == 'x86_64': config.environment['ASAN_OPTIONS'] = 'detect_leaks=1' diff --git a/test/asan/lit.cfg b/test/asan/lit.cfg index f24e68037..7f47b43ed 100644 --- a/test/asan/lit.cfg +++ b/test/asan/lit.cfg @@ -11,6 +11,11 @@ def get_required_attr(config, attr_name): "to lit.site.cfg " % attr_name) return attr_value +def push_ld_library_path(config, new_path): + new_ld_library_path = os.path.pathsep.join( + (new_path, config.environment['LD_LIBRARY_PATH'])) + config.environment['LD_LIBRARY_PATH'] = new_ld_library_path + # Setup config name. config.name = 'AddressSanitizer' + config.name_suffix @@ -27,12 +32,21 @@ else: # FIXME: Review the set of required flags and check if it can be reduced. target_cflags = [get_required_attr(config, "target_cflags")] + extra_linkflags target_cxxflags = config.cxx_mode_flags + target_cflags -clang_asan_cflags = ["-fsanitize=address", - "-mno-omit-leaf-frame-pointer", - "-fno-omit-frame-pointer", - "-fno-optimize-sibling-calls", - "-g"] + target_cflags -clang_asan_cxxflags = config.cxx_mode_flags + clang_asan_cflags +clang_asan_static_cflags = ["-fsanitize=address", + "-mno-omit-leaf-frame-pointer", + "-fno-omit-frame-pointer", + "-fno-optimize-sibling-calls", + "-g"] + target_cflags +clang_asan_static_cxxflags = config.cxx_mode_flags + clang_asan_static_cflags + +if config.asan_dynamic: + clang_asan_cflags = clang_asan_static_cflags + ['-shared-libasan'] + clang_asan_cxxflags = clang_asan_static_cxxflags + ['-shared-libasan'] + config.available_features.add("asan-dynamic-runtime") +else: + clang_asan_cflags = clang_asan_static_cflags + clang_asan_cxxflags = clang_asan_static_cxxflags + config.available_features.add("asan-static-runtime") asan_lit_source_dir = get_required_attr(config, "asan_lit_source_dir") if config.android == "TRUE": @@ -49,6 +63,10 @@ config.substitutions.append( ("%clang ", build_invocation(target_cflags)) ) config.substitutions.append( ("%clangxx ", build_invocation(target_cxxflags)) ) config.substitutions.append( ("%clang_asan ", build_invocation(clang_asan_cflags)) ) config.substitutions.append( ("%clangxx_asan ", build_invocation(clang_asan_cxxflags)) ) +config.substitutions.append( ("%shared_libasan", "libclang_rt.asan-%s.so" % config.target_arch)) +if config.asan_dynamic: + config.substitutions.append( ("%clang_asan_static ", build_invocation(clang_asan_static_cflags)) ) + config.substitutions.append( ("%clangxx_asan_static ", build_invocation(clang_asan_static_cxxflags)) ) # FIXME: De-hardcode this path. asan_source_dir = os.path.join( @@ -76,14 +94,14 @@ config.available_features.add("asan-" + config.bits + "-bits") if config.host_os == 'Linux' and config.bits == '64': config.environment['ASAN_OPTIONS'] = 'detect_leaks=1' -# GCC-ASan uses dynamic runtime by default, so we have to set LD_LIBRARY_PATH -# to pick it up properly. +# Set LD_LIBRARY_PATH to pick dynamic runtime up properly. +push_ld_library_path(config, config.compiler_rt_libdir) + +# GCC-ASan uses dynamic runtime by default. if config.compiler_id == 'GNU': gcc_dir = os.path.dirname(config.clang) libasan_dir = os.path.join(gcc_dir, "..", "lib" + config.bits) - new_ld_library_path = os.path.pathsep.join( - (libasan_dir, config.environment['LD_LIBRARY_PATH'])) - config.environment['LD_LIBRARY_PATH'] = new_ld_library_path + push_ld_library_path(config, libasan_dir) # Default test suffixes. config.suffixes = ['.c', '.cc', '.cpp'] diff --git a/test/asan/lit.site.cfg.in b/test/asan/lit.site.cfg.in index 48ea81252..76e0c5542 100644 --- a/test/asan/lit.site.cfg.in +++ b/test/asan/lit.site.cfg.in @@ -9,6 +9,8 @@ config.clang = "@ASAN_TEST_TARGET_CC@" config.llvm_tools_dir = "@ASAN_TEST_LLVM_TOOLS_DIR@" config.bits = "@ASAN_TEST_BITS@" config.android = "@CAN_TARGET_arm_android@" +config.asan_dynamic = @ASAN_TEST_DYNAMIC@ +config.target_arch = "@ASAN_TEST_TARGET_ARCH@" # Load common config for all compiler-rt lit tests. lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") |