summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/CMakeLists.txt15
-rw-r--r--test/asan/CMakeLists.txt10
-rw-r--r--test/asan/TestCases/Android/coverage-android.cc4
-rw-r--r--test/asan/TestCases/Darwin/cstring_section.c17
-rw-r--r--test/asan/TestCases/Darwin/dead-strip.c22
-rw-r--r--test/asan/TestCases/Darwin/dump_registers.cc26
-rw-r--r--test/asan/TestCases/Darwin/malloc_destroy_zone.cc21
-rw-r--r--test/asan/TestCases/Darwin/odr-lto.cc45
-rw-r--r--test/asan/TestCases/Linux/abort_on_error.cc2
-rw-r--r--test/asan/TestCases/Linux/auto_memory_profile_test.cc32
-rw-r--r--test/asan/TestCases/Linux/coverage_html_report.cc24
-rw-r--r--test/asan/TestCases/Linux/cuda_test.cc37
-rw-r--r--test/asan/TestCases/Linux/local_alias.cc5
-rw-r--r--test/asan/TestCases/Linux/malloc_delete_mismatch.cc3
-rw-r--r--test/asan/TestCases/Linux/memmem_test.cc13
-rw-r--r--test/asan/TestCases/Linux/new_delete_mismatch.cc4
-rw-r--r--test/asan/TestCases/Linux/odr-violation.cc5
-rw-r--r--test/asan/TestCases/Linux/print_memory_profile_test.cc24
-rw-r--r--test/asan/TestCases/Linux/pthread_create_from_constructor.cc49
-rw-r--r--test/asan/TestCases/Linux/quarantine_size_mb.cc2
-rw-r--r--test/asan/TestCases/Linux/release_to_os_test.cc46
-rw-r--r--test/asan/TestCases/Linux/stack-trace-dlclose.cc3
-rw-r--r--test/asan/TestCases/Linux/swapcontext_annotation.cc74
-rw-r--r--test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc40
-rw-r--r--test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc4
-rw-r--r--test/asan/TestCases/Posix/coverage-fork.cc2
-rw-r--r--test/asan/TestCases/Posix/halt_on_error-signals.c2
-rw-r--r--test/asan/TestCases/Posix/halt_on_error-torture.cc11
-rw-r--r--test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc6
-rw-r--r--test/asan/TestCases/Posix/handle_abort_on_error.cc9
-rw-r--r--test/asan/TestCases/Posix/no_asan_gen_globals.c (renamed from test/asan/TestCases/no_asan_gen_globals.c)1
-rw-r--r--test/asan/TestCases/Posix/start-deactivated.cc41
-rw-r--r--test/asan/TestCases/Windows/bind_io_completion_callback.cc5
-rw-r--r--test/asan/TestCases/Windows/coverage-dll-stdio.cc16
-rw-r--r--test/asan/TestCases/Windows/default_options.cc18
-rw-r--r--test/asan/TestCases/Windows/delay_dbghelp.cc18
-rw-r--r--test/asan/TestCases/Windows/dll_global_dead_strip.c28
-rw-r--r--test/asan/TestCases/Windows/dll_host.cc31
-rw-r--r--test/asan/TestCases/Windows/dll_intercept_memchr.cc6
-rw-r--r--test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc2
-rw-r--r--test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc4
-rw-r--r--test/asan/TestCases/Windows/free_hook_realloc.cc3
-rw-r--r--test/asan/TestCases/Windows/global_dead_strip.c23
-rw-r--r--test/asan/TestCases/Windows/intercept_memcpy.cc4
-rw-r--r--test/asan/TestCases/Windows/on_error_callback.cc20
-rw-r--r--test/asan/TestCases/Windows/oom.cc1
-rw-r--r--test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc4
-rw-r--r--test/asan/TestCases/Windows/queue_user_work_item.cc5
-rw-r--r--test/asan/TestCases/Windows/queue_user_work_item_report.cc2
-rw-r--r--test/asan/TestCases/Windows/report_after_syminitialize.cc6
-rw-r--r--test/asan/TestCases/Windows/shadow_conflict_32.cc29
-rw-r--r--test/asan/TestCases/Windows/shadow_mapping_failure.cc1
-rw-r--r--test/asan/TestCases/Windows/tls_init.cc51
-rw-r--r--test/asan/TestCases/Windows/unsymbolized.cc4
-rw-r--r--test/asan/TestCases/alloca_big_alignment.cc2
-rw-r--r--test/asan/TestCases/alloca_detect_custom_size_.cc2
-rw-r--r--test/asan/TestCases/alloca_instruments_all_paddings.cc4
-rw-r--r--test/asan/TestCases/alloca_loop_unpoisoning.cc2
-rw-r--r--test/asan/TestCases/alloca_overflow_partial.cc2
-rw-r--r--test/asan/TestCases/alloca_overflow_right.cc2
-rw-r--r--test/asan/TestCases/alloca_safe_access.cc2
-rw-r--r--test/asan/TestCases/alloca_underflow_left.cc2
-rw-r--r--test/asan/TestCases/alloca_vla_interact.cc2
-rw-r--r--test/asan/TestCases/atexit_stats.cc4
-rw-r--r--test/asan/TestCases/coverage-order-pcs.cc2
-rw-r--r--test/asan/TestCases/coverage-pc-buffer.cc65
-rw-r--r--test/asan/TestCases/coverage-tracing.cc2
-rw-r--r--test/asan/TestCases/debug_double_free.cc50
-rw-r--r--test/asan/TestCases/debug_mapping.cc8
-rw-r--r--test/asan/TestCases/debug_report.cc3
-rw-r--r--test/asan/TestCases/debug_stacks.cc14
-rw-r--r--test/asan/TestCases/deep_stack_uaf.cc3
-rw-r--r--test/asan/TestCases/default_options.cc3
-rw-r--r--test/asan/TestCases/double-free.cc4
-rw-r--r--test/asan/TestCases/exitcode.cc130
-rw-r--r--test/asan/TestCases/global-address.cpp12
-rw-r--r--test/asan/TestCases/ill.cc31
-rw-r--r--test/asan/TestCases/initialization-bug.cc4
-rw-r--r--test/asan/TestCases/interception_failure_test.cc11
-rw-r--r--test/asan/TestCases/intra-object-overflow.cc2
-rw-r--r--test/asan/TestCases/invalid-free.cc3
-rw-r--r--test/asan/TestCases/large_func_test.cc3
-rw-r--r--test/asan/TestCases/on_error_callback.cc3
-rw-r--r--test/asan/TestCases/printf-m.c14
-rw-r--r--test/asan/TestCases/sanity_check_pure_c.c5
-rw-r--r--test/asan/TestCases/scariness_score_test.cc (renamed from test/asan/TestCases/Linux/scariness_score_test.cc)28
-rw-r--r--test/asan/TestCases/set_shadow_test.c69
-rw-r--r--test/asan/TestCases/speculative_load.cc4
-rw-r--r--test/asan/TestCases/strdup_oob_test.cc4
-rw-r--r--test/asan/TestCases/strncasecmp_strict.c67
-rw-r--r--test/asan/TestCases/strncmp_strict.c65
-rw-r--r--test/asan/TestCases/strncpy-overflow.cc3
-rw-r--r--test/asan/TestCases/strstr-1.c2
-rw-r--r--test/asan/TestCases/strstr_strict.c2
-rw-r--r--test/asan/TestCases/suppressions-library.cc2
-rw-r--r--test/asan/TestCases/use-after-delete.cc3
-rw-r--r--test/asan/TestCases/use-after-free-right.cc3
-rw-r--r--test/asan/TestCases/use-after-free.cc3
-rw-r--r--test/asan/TestCases/use-after-scope-capture.cc2
-rw-r--r--test/asan/TestCases/use-after-scope-chars.cc15
-rw-r--r--test/asan/TestCases/use-after-scope-goto.cc73
-rw-r--r--test/asan/TestCases/use-after-scope-inlined.cc2
-rw-r--r--test/asan/TestCases/use-after-scope-loop-bug.cc9
-rw-r--r--test/asan/TestCases/use-after-scope-loop-removed.cc9
-rw-r--r--test/asan/TestCases/use-after-scope-temp.cc12
-rw-r--r--test/asan/TestCases/use-after-scope-temp2.cc20
-rw-r--r--test/asan/TestCases/use-after-scope-types.cc74
-rw-r--r--test/asan/TestCases/use-after-scope.cc5
-rw-r--r--test/asan/TestCases/vla_chrome_testcase.cc2
-rw-r--r--test/asan/TestCases/vla_condition_overflow.cc2
-rw-r--r--test/asan/TestCases/vla_loop_overfow.cc2
-rwxr-xr-xtest/asan/android_commands/android_run.py12
-rw-r--r--test/asan/lit.cfg56
-rw-r--r--test/builtins/Unit/cpu_model_test.c2
-rw-r--r--test/builtins/Unit/negdf2vfp_test.c3
-rw-r--r--test/builtins/Unit/subdf3vfp_test.c1
-rw-r--r--test/cfi/CMakeLists.txt13
-rw-r--r--test/cfi/cross-dso/stats.cpp8
-rw-r--r--test/cfi/icall/weak.c15
-rw-r--r--test/cfi/simple-fail.cpp6
-rw-r--r--test/cfi/two-vcalls.cpp60
-rw-r--r--test/dfsan/CMakeLists.txt11
-rw-r--r--test/dfsan/custom.cc2
-rw-r--r--test/dfsan/write_callback.c1
-rw-r--r--test/esan/TestCases/mmap-shadow-conflict.c24
-rw-r--r--test/esan/TestCases/struct-simple.cpp44
-rw-r--r--test/esan/TestCases/verbose-simple.c18
-rw-r--r--test/esan/Unit/hashtable.cpp179
-rw-r--r--test/esan/lit.cfg2
-rw-r--r--test/interception/CMakeLists.txt17
-rw-r--r--test/interception/Unit/lit.site.cfg.in14
-rw-r--r--test/lit.common.cfg16
-rw-r--r--test/lit.common.configured.in3
-rw-r--r--test/lsan/CMakeLists.txt11
-rw-r--r--test/lsan/TestCases/cleanup_in_tsd_destructor.c5
-rw-r--r--test/lsan/TestCases/guard-page.c5
-rw-r--r--test/lsan/TestCases/large_allocation_leak.cc5
-rw-r--r--test/lsan/TestCases/pointer_to_self.cc5
-rw-r--r--test/lsan/TestCases/stale_stack_leak.cc11
-rw-r--r--test/lsan/TestCases/strace_test.cc14
-rw-r--r--test/lsan/TestCases/use_after_return.cc7
-rw-r--r--test/lsan/TestCases/use_globals_initialized.cc5
-rw-r--r--test/lsan/TestCases/use_globals_uninitialized.cc5
-rw-r--r--test/lsan/TestCases/use_poisoned_asan.cc5
-rw-r--r--test/lsan/TestCases/use_registers.cc5
-rw-r--r--test/lsan/TestCases/use_stacks.cc5
-rw-r--r--test/lsan/TestCases/use_stacks_threaded.cc5
-rw-r--r--test/lsan/TestCases/use_tls_dynamic.cc5
-rw-r--r--test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc5
-rw-r--r--test/lsan/TestCases/use_tls_pthread_specific_static.cc5
-rw-r--r--test/lsan/TestCases/use_tls_static.cc5
-rw-r--r--test/lsan/TestCases/use_unaligned.cc5
-rw-r--r--test/lsan/lit.common.cfg5
-rw-r--r--test/msan/CMakeLists.txt11
-rw-r--r--test/msan/Linux/forkpty.cc7
-rw-r--r--test/msan/Linux/obstack.cc4
-rw-r--r--test/msan/Linux/process_vm_readv.cc2
-rw-r--r--test/msan/Linux/syscalls_sigaction.cc8
-rw-r--r--test/msan/allocator_mapping.cc2
-rw-r--r--test/msan/backtrace.cc2
-rw-r--r--test/msan/chained_origin.cc25
-rw-r--r--test/msan/chained_origin_limits.cc26
-rw-r--r--test/msan/chained_origin_memcpy.cc21
-rw-r--r--test/msan/coverage-levels.cc2
-rw-r--r--test/msan/fork.cc7
-rw-r--r--test/msan/getutent.cc17
-rw-r--r--test/msan/iconv.cc2
-rw-r--r--test/msan/lit.cfg8
-rw-r--r--test/msan/mmap.cc10
-rw-r--r--test/msan/msan_check_mem_is_initialized.cc2
-rw-r--r--test/msan/msan_copy_shadow.cc7
-rw-r--r--test/msan/print_stats.cc18
-rw-r--r--test/msan/realloc-large-origin.cc11
-rw-r--r--test/msan/recover-dso.cc (renamed from test/msan/keep-going-dso.cc)30
-rw-r--r--test/msan/recover.cc (renamed from test/msan/keep-going.cc)31
-rw-r--r--test/msan/strlen_of_shadow.cc2
-rw-r--r--test/profile/CMakeLists.txt8
-rw-r--r--test/profile/Inputs/comdat_rename.h13
-rw-r--r--test/profile/Inputs/comdat_rename_1.cc33
-rw-r--r--test/profile/Inputs/comdat_rename_2.cc18
-rw-r--r--test/profile/Inputs/extern_template.h10
-rw-r--r--test/profile/Inputs/instrprof-comdat.h16
-rw-r--r--test/profile/Inputs/instrprof-dynamic-a.cpp10
-rw-r--r--test/profile/Linux/comdat_rename.test6
-rw-r--r--test/profile/Linux/coverage_ctors.cpp8
-rw-r--r--test/profile/Linux/coverage_dtor.cpp4
-rw-r--r--test/profile/Linux/coverage_test.cpp26
-rw-r--r--test/profile/Linux/extern_template.test4
-rw-r--r--test/profile/Linux/instrprof-comdat.test2
-rw-r--r--test/profile/Linux/instrprof-cs.c35
-rw-r--r--test/profile/Linux/lit.local.cfg1
-rw-r--r--test/profile/gcc-flag-compatibility.test8
-rw-r--r--test/profile/instrprof-basic.c43
-rw-r--r--test/profile/instrprof-darwin-dead-strip.c60
-rw-r--r--test/profile/instrprof-dump.c62
-rw-r--r--test/profile/instrprof-icall-promo.test14
-rw-r--r--test/profile/instrprof-override-filename-then-reset-default.c6
-rw-r--r--test/profile/instrprof-override-filename-with-env.c6
-rw-r--r--test/profile/instrprof-override-filename.c6
-rw-r--r--test/profile/instrprof-path.c39
-rw-r--r--test/profile/instrprof-set-filename-shared.test (renamed from test/profile/Linux/instrprof-set-filename-shared.test)4
-rw-r--r--test/profile/instrprof-value-prof-evict.test4
-rw-r--r--test/profile/instrprof-value-prof-reset.c47
-rw-r--r--test/profile/instrprof-value-prof-shared.test27
-rw-r--r--test/profile/instrprof-value-prof.test4
-rw-r--r--test/profile/instrprof-visibility.cpp52
-rw-r--r--test/profile/lit.cfg23
-rw-r--r--test/safestack/lit.cfg1
-rw-r--r--test/sanitizer_common/CMakeLists.txt13
-rw-r--r--test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc1
-rw-r--r--test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc12
-rw-r--r--test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc63
-rw-r--r--test/sanitizer_common/TestCases/printf-ldbl.c13
-rw-r--r--test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc72
-rw-r--r--test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc41
-rw-r--r--test/sanitizer_common/TestCases/scanf-ldbl.c13
-rw-r--r--test/sanitizer_common/TestCases/symbolize_pc.cc41
-rw-r--r--test/sanitizer_common/print_address.h19
-rw-r--r--test/scudo/CMakeLists.txt31
-rw-r--r--test/scudo/alignment.cpp7
-rw-r--r--test/scudo/double-free.cpp2
-rw-r--r--test/scudo/interface.cpp28
-rw-r--r--test/scudo/lit.cfg13
-rw-r--r--test/scudo/lit.site.cfg.in4
-rw-r--r--test/scudo/malloc.cpp27
-rw-r--r--test/scudo/memalign.cpp41
-rw-r--r--test/scudo/mismatch.cpp2
-rw-r--r--test/scudo/options.cpp25
-rw-r--r--test/scudo/overflow.cpp5
-rw-r--r--test/scudo/preinit.cpp1
-rw-r--r--test/scudo/random_shuffle.cpp24
-rw-r--r--test/scudo/realloc.cpp90
-rw-r--r--test/scudo/secondary.cpp54
-rw-r--r--test/tsan/CMakeLists.txt10
-rw-r--r--test/tsan/Darwin/gcd-apply-race.mm4
-rw-r--r--test/tsan/Darwin/gcd-apply.mm4
-rw-r--r--test/tsan/Darwin/gcd-suspend.mm45
-rw-r--r--test/tsan/Darwin/gcd-target-queue-norace.mm41
-rw-r--r--test/tsan/Darwin/libcxx-call-once.mm34
-rw-r--r--test/tsan/Darwin/libcxx-future.mm30
-rw-r--r--test/tsan/Darwin/norace-objcxx-run-time.mm113
-rw-r--r--test/tsan/Darwin/objc-double-property.mm21
-rw-r--r--test/tsan/Darwin/osatomics-bitops.mm34
-rw-r--r--test/tsan/Darwin/realloc-zero.cc20
-rw-r--r--test/tsan/atomic_free.cc13
-rw-r--r--test/tsan/atomic_store.cc49
-rw-r--r--test/tsan/debug_alloc_stack.cc84
-rw-r--r--test/tsan/debug_locate.cc43
-rw-r--r--test/tsan/exceptions.cc185
-rw-r--r--test/tsan/fork_atexit.cc2
-rw-r--r--test/tsan/global_race.cc13
-rw-r--r--test/tsan/ignore_lib4.cc2
-rw-r--r--test/tsan/ignore_lib5.cc75
-rw-r--r--test/tsan/ignore_lib5.cc.supp2
-rw-r--r--test/tsan/java.h1
-rw-r--r--test/tsan/libcxx/lit.local.cfg4
-rw-r--r--test/tsan/lit.cfg11
-rw-r--r--test/tsan/longjmp.cc3
-rw-r--r--test/tsan/longjmp2.cc3
-rw-r--r--test/tsan/longjmp3.cc3
-rw-r--r--test/tsan/longjmp4.cc3
-rw-r--r--test/tsan/map32bit.cc2
-rw-r--r--test/tsan/pie_test.cc6
-rw-r--r--test/tsan/signal_block.cc60
-rw-r--r--test/tsan/signal_cond.cc2
-rw-r--r--test/tsan/signal_longjmp.cc2
-rw-r--r--test/tsan/simple_stack.c41
-rw-r--r--test/tsan/test.h19
-rw-r--r--test/ubsan/CMakeLists.txt8
-rw-r--r--test/ubsan/TestCases/TypeCheck/null.cpp32
-rw-r--r--test/ubsan/TestCases/TypeCheck/vptr.cpp9
-rw-r--r--test/xray/CMakeLists.txt48
-rw-r--r--test/xray/TestCases/Linux/fixedsize-logging.cc20
-rw-r--r--test/xray/TestCases/Linux/optional-inmemory-log.cc21
-rw-r--r--test/xray/TestCases/Linux/patching-unpatching.cc48
-rw-r--r--test/xray/Unit/lit.site.cfg.in12
-rw-r--r--test/xray/lit.cfg39
-rw-r--r--test/xray/lit.site.cfg.in13
278 files changed, 4268 insertions, 851 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 03d4571e0de78..9b9c515a304d2 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -23,7 +23,7 @@ if(NOT ANDROID)
# Use LLVM utils and Clang from the same build tree.
list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS
clang clang-headers FileCheck count not llvm-config llvm-nm llvm-objdump
- llvm-symbolizer compiler-rt-headers sancov)
+ llvm-readobj llvm-symbolizer compiler-rt-headers sancov)
if (COMPILER_RT_HAS_PROFILE)
list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS profile)
endif()
@@ -45,6 +45,9 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS)
if(COMPILER_RT_HAS_DFSAN)
add_subdirectory(dfsan)
endif()
+ if (COMPILER_RT_HAS_INTERCEPTION)
+ add_subdirectory(interception)
+ endif()
if(COMPILER_RT_HAS_LSAN)
add_subdirectory(lsan)
endif()
@@ -76,6 +79,9 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS)
if(COMPILER_RT_HAS_SCUDO)
add_subdirectory(scudo)
endif()
+ if(COMPILER_RT_HAS_XRAY)
+ add_subdirectory(xray)
+ endif()
endif()
if(COMPILER_RT_STANDALONE_BUILD)
@@ -83,8 +89,13 @@ if(COMPILER_RT_STANDALONE_BUILD)
# introduce a rule to run to run all of them.
get_property(LLVM_LIT_TESTSUITES GLOBAL PROPERTY LLVM_LIT_TESTSUITES)
get_property(LLVM_LIT_DEPENDS GLOBAL PROPERTY LLVM_LIT_DEPENDS)
- add_lit_target(check-all
+ add_lit_target(check-compiler-rt
"Running all regression tests"
${LLVM_LIT_TESTSUITES}
DEPENDS ${LLVM_LIT_DEPENDS})
+ if(NOT TARGET check-all)
+ add_custom_target(check-all)
+ endif()
+ add_custom_target(compiler-rt-test-depends DEPENDS ${LLVM_LIT_DEPENDS})
+ add_dependencies(check-all check-compiler-rt)
endif()
diff --git a/test/asan/CMakeLists.txt b/test/asan/CMakeLists.txt
index cb32cfba83b04..637c5b80802cd 100644
--- a/test/asan/CMakeLists.txt
+++ b/test/asan/CMakeLists.txt
@@ -43,15 +43,7 @@ foreach(arch ${ASAN_TEST_ARCH})
endif()
string(TOLOWER "-${arch}-${OS_NAME}" ASAN_TEST_CONFIG_SUFFIX)
get_bits_for_arch(${arch} ASAN_TEST_BITS)
- if(ANDROID OR ${arch} MATCHES "arm|aarch64")
- # This is only true if we are cross-compiling.
- # Build all tests with host compiler and use host tools.
- set(ASAN_TEST_TARGET_CC ${COMPILER_RT_TEST_COMPILER})
- set(ASAN_TEST_TARGET_CFLAGS ${COMPILER_RT_TEST_COMPILER_CFLAGS})
- else()
- get_target_flags_for_arch(${arch} ASAN_TEST_TARGET_CFLAGS)
- string(REPLACE ";" " " ASAN_TEST_TARGET_CFLAGS "${ASAN_TEST_TARGET_CFLAGS}")
- endif()
+ get_test_cc_for_arch(${arch} ASAN_TEST_TARGET_CC ASAN_TEST_TARGET_CFLAGS)
if(ANDROID)
set(ASAN_TEST_DYNAMIC True)
else()
diff --git a/test/asan/TestCases/Android/coverage-android.cc b/test/asan/TestCases/Android/coverage-android.cc
index 2a3359948691d..cf4f33ebdb446 100644
--- a/test/asan/TestCases/Android/coverage-android.cc
+++ b/test/asan/TestCases/Android/coverage-android.cc
@@ -101,6 +101,10 @@
// RUN: %sancov rawunpack *.sancov.raw
// RUN: %sancov print *.sancov |& FileCheck --check-prefix=CHECK3 %s
+// PC counts in CHECK lines are platform dependent and match arm32 at the moment.
+// sancov tool does not support Android well enough to match function names
+// REQUIRES: arm
+
#include <assert.h>
#include <dlfcn.h>
#include <stdio.h>
diff --git a/test/asan/TestCases/Darwin/cstring_section.c b/test/asan/TestCases/Darwin/cstring_section.c
new file mode 100644
index 0000000000000..952d6fcdd4656
--- /dev/null
+++ b/test/asan/TestCases/Darwin/cstring_section.c
@@ -0,0 +1,17 @@
+// Test that AddressSanitizer moves constant strings into a separate section.
+
+// RUN: %clang_asan -c -o %t %s
+// RUN: llvm-objdump -s %t | FileCheck %s
+
+// Check that "Hello.\n" is in __asan_cstring and not in __cstring.
+// CHECK: Contents of section __asan_cstring:
+// CHECK: 48656c6c {{.*}} Hello.
+// CHECK: Contents of section __const:
+// CHECK-NOT: 48656c6c {{.*}} Hello.
+// CHECK: Contents of section __cstring:
+// CHECK-NOT: 48656c6c {{.*}} Hello.
+
+int main(int argc, char *argv[]) {
+ argv[0] = "Hello.\n";
+ return 0;
+}
diff --git a/test/asan/TestCases/Darwin/dead-strip.c b/test/asan/TestCases/Darwin/dead-strip.c
new file mode 100644
index 0000000000000..f87a5e52b1cf1
--- /dev/null
+++ b/test/asan/TestCases/Darwin/dead-strip.c
@@ -0,0 +1,22 @@
+// Test that AddressSanitizer does not re-animate dead globals when dead
+// stripping is turned on.
+//
+// This test verifies that an out-of-bounds access on a global variable is
+// detected after dead stripping has been performed. This proves that the
+// runtime is able to register globals in the __DATA,__asan_globals section.
+
+// REQUIRES: osx-ld64-live_support
+// RUN: %clang_asan -mmacosx-version-min=10.11 -Xlinker -dead_strip -o %t %s
+// RUN: llvm-nm -format=posix %t | FileCheck --check-prefix NM-CHECK %s
+// RUN: not %run %t 2>&1 | FileCheck --check-prefix ASAN-CHECK %s
+
+int alive[1] = {};
+int dead[1] = {};
+// NM-CHECK: {{^_alive }}
+// NM-CHECK-NOT: {{^_dead }}
+
+int main(int argc, char *argv[]) {
+ alive[argc] = 0;
+ // ASAN-CHECK: {{0x.* is located 0 bytes to the right of global variable}}
+ return 0;
+}
diff --git a/test/asan/TestCases/Darwin/dump_registers.cc b/test/asan/TestCases/Darwin/dump_registers.cc
new file mode 100644
index 0000000000000..884ad2ed44c07
--- /dev/null
+++ b/test/asan/TestCases/Darwin/dump_registers.cc
@@ -0,0 +1,26 @@
+// Check that ASan dumps the CPU registers on a SIGSEGV.
+
+// RUN: %clangxx_asan %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <stdio.h>
+
+int main() {
+ fprintf(stderr, "Hello\n");
+ char *ptr;
+
+ if (sizeof(void *) == 8)
+ ptr = (char *)0x6666666666666666;
+ else if (sizeof(void *) == 4)
+ ptr = (char *)0x55555555;
+ else
+ assert(0 && "Your computer is weird.");
+
+ char c = *ptr; // BOOM
+ // CHECK: ERROR: AddressSanitizer: SEGV
+ // CHECK: Register values:
+ // CHECK: {{0x55555555|0x6666666666666666}}
+ fprintf(stderr, "World\n");
+ return c;
+}
diff --git a/test/asan/TestCases/Darwin/malloc_destroy_zone.cc b/test/asan/TestCases/Darwin/malloc_destroy_zone.cc
new file mode 100644
index 0000000000000..9144bd689f744
--- /dev/null
+++ b/test/asan/TestCases/Darwin/malloc_destroy_zone.cc
@@ -0,0 +1,21 @@
+// RUN: %clangxx_asan %s -o %t && %run %t 2>&1 | FileCheck %s
+
+#include <malloc/malloc.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int main() {
+ fprintf(stderr, "start\n");
+ malloc_zone_t *zone = malloc_create_zone(0, 0);
+ fprintf(stderr, "zone = %p\n", zone);
+ malloc_set_zone_name(zone, "myzone");
+ fprintf(stderr, "name changed\n");
+ malloc_destroy_zone(zone);
+ fprintf(stderr, "done\n");
+ return 0;
+}
+
+// CHECK: start
+// CHECK-NEXT: zone = 0x{{.*}}
+// CHECK-NEXT: name changed
+// CHECK-NEXT: done
diff --git a/test/asan/TestCases/Darwin/odr-lto.cc b/test/asan/TestCases/Darwin/odr-lto.cc
new file mode 100644
index 0000000000000..40abec5827d5f
--- /dev/null
+++ b/test/asan/TestCases/Darwin/odr-lto.cc
@@ -0,0 +1,45 @@
+// Check that -asan-use-private-alias and use_odr_indicator=1 silence the false
+// positive ODR violation on Darwin with LTO.
+
+// REQUIRES: lto
+
+// RUN: %clangxx_asan -DPART=0 -c %s -o %t-1.o -flto
+// RUN: %clangxx_asan -DPART=1 -c %s -o %t-2.o -flto
+// RUN: %clangxx_asan %t-1.o %t-2.o -o %t -flto
+// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-ODR
+
+// RUN: %clangxx_asan -DPART=0 -c %s -o %t-1.o -flto -mllvm -asan-use-private-alias
+// RUN: %clangxx_asan -DPART=1 -c %s -o %t-2.o -flto -mllvm -asan-use-private-alias
+// RUN: %clangxx_asan %t-1.o %t-2.o -o %t -flto
+// RUN: %env_asan_opts=use_odr_indicator=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NO-ODR
+
+#include <stdio.h>
+#include <stdlib.h>
+void putstest();
+
+#if PART == 1
+
+static const char *my_global = "test\n\00abc";
+
+int main()
+{
+ fputs(my_global, stderr);
+ putstest();
+ fprintf(stderr, "Done.\n");
+ return 0;
+}
+
+#else // PART == 1
+
+static const char *my_other_global = "test\n\00abc";
+
+void putstest()
+{
+ fputs(my_other_global, stderr);
+}
+
+#endif // PART == 1
+
+// CHECK-ODR: ERROR: AddressSanitizer: odr-violation
+// CHECK-NO-ODR-NOT: ERROR: AddressSanitizer: odr-violation
+// CHECK-NO-ODR: Done.
diff --git a/test/asan/TestCases/Linux/abort_on_error.cc b/test/asan/TestCases/Linux/abort_on_error.cc
index 67fa9b83e65d9..3f70613e4c7c1 100644
--- a/test/asan/TestCases/Linux/abort_on_error.cc
+++ b/test/asan/TestCases/Linux/abort_on_error.cc
@@ -9,6 +9,8 @@
// lit doesn't set ASAN_OPTIONS anyway.
// RUN: not %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: android
+
#include <stdlib.h>
int main() {
char *x = (char*)malloc(10 * sizeof(char));
diff --git a/test/asan/TestCases/Linux/auto_memory_profile_test.cc b/test/asan/TestCases/Linux/auto_memory_profile_test.cc
new file mode 100644
index 0000000000000..3f8ad4673e756
--- /dev/null
+++ b/test/asan/TestCases/Linux/auto_memory_profile_test.cc
@@ -0,0 +1,32 @@
+// Tests heap_profile=1.
+// Printing memory profiling only works in the configuration where we can
+// detect leaks.
+// REQUIRES: leak-detection
+//
+// RUN: %clangxx_asan %s -o %t
+// RUN: %env_asan_opts=heap_profile=1 %run %t 2>&1 | FileCheck %s
+#include <sanitizer/common_interface_defs.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+char *sink[1000];
+
+int main() {
+
+ for (int i = 0; i < 3; i++) {
+ const size_t kSize = 13000000;
+ char *x = new char[kSize];
+ memset(x, 0, kSize);
+ sink[i] = x;
+ sleep(1);
+ }
+}
+
+// CHECK: HEAP PROFILE at RSS
+// CHECK: 13000000 byte(s)
+// CHECK: HEAP PROFILE at RSS
+// CHECK: 26000000 byte(s)
+// CHECK: HEAP PROFILE at RSS
+// CHECK: 39000000 byte(s)
diff --git a/test/asan/TestCases/Linux/coverage_html_report.cc b/test/asan/TestCases/Linux/coverage_html_report.cc
deleted file mode 100644
index 78fbfb3724030..0000000000000
--- a/test/asan/TestCases/Linux/coverage_html_report.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// REQUIRES: has_sancovcc, x86_64-linux, asan-dynamic-runtime
-// RUN: %clangxx_asan_static -fsanitize-coverage=func %s -o %t
-// RUN: rm -rf %T/coverage_html_report
-// RUN: mkdir -p %T/coverage_html_report
-// RUN: cd %T/coverage_html_report
-// RUN: %env_asan_opts=coverage=1:verbosity=1:html_cov_report=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-main
-// RUN: ls *.html | FileCheck %s --check-prefix=CHECK-ls
-// RUN: rm -r %T/coverage_html_report
-
-#include <stdio.h>
-#include <unistd.h>
-
-void bar() { printf("bar\n"); }
-
-int main(int argc, char **argv) {
- fprintf(stderr, "PID: %d\n", getpid());
- bar();
- return 0;
-}
-
-// CHECK-main: PID: [[PID:[0-9]+]]
-// CHECK-main: [[PID]].sancov: 2 PCs written
-// CHECK-main: coverage report generated to ./coverage_html_report.cc.tmp.[[PID]].html
-// CHECK-ls: coverage_html_report.cc.tmp.{{[0-9]+}}.html
diff --git a/test/asan/TestCases/Linux/cuda_test.cc b/test/asan/TestCases/Linux/cuda_test.cc
new file mode 100644
index 0000000000000..e87f56b0c20e2
--- /dev/null
+++ b/test/asan/TestCases/Linux/cuda_test.cc
@@ -0,0 +1,37 @@
+// Emulate the behavior of the NVIDIA CUDA driver
+// that mmaps memory inside the asan's shadow gap.
+//
+// REQUIRES: x86_64-target-arch
+//
+// RUN: %clangxx_asan %s -o %t
+// RUN: not %env_asan_opts=protect_shadow_gap=1 %t 2>&1 | FileCheck %s --check-prefix=CHECK-PROTECT1
+// RUN: not %t 2>&1 | FileCheck %s --check-prefix=CHECK-PROTECT1
+// RUN: not %env_asan_opts=protect_shadow_gap=0 %t 2>&1 | FileCheck %s --check-prefix=CHECK-PROTECT0
+#include <assert.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdint.h>
+
+#include "sanitizer/asan_interface.h"
+
+int main(void) {
+ uintptr_t Base = 0x200000000;
+ uintptr_t Size = 0x1100000000;
+ void *addr =
+ mmap((void *)Base, Size, PROT_READ | PROT_WRITE,
+ MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0);
+ assert(addr == (void*)Base);
+ // Make sure we can access memory in shadow gap.
+ // W/o protect_shadow_gap=0 we should fail here.
+ for (uintptr_t Addr = Base; Addr < Base + Size; Addr += Size / 100)
+ *(char*)Addr = 1;
+ // CHECK-PROTECT1: AddressSanitizer: SEGV on unknown address 0x0000bfff8000
+
+ // Poison a part of gap's shadow:
+ __asan_poison_memory_region((void*)Base, 4096);
+ // Now we should fail with use-after-poison.
+ *(char*)(Base + 1234) = 1;
+ // CHECK-PROTECT0: AddressSanitizer: use-after-poison on address 0x0002000004d2
+}
+
+
diff --git a/test/asan/TestCases/Linux/local_alias.cc b/test/asan/TestCases/Linux/local_alias.cc
index d941ff2f9171a..8c80f878594df 100644
--- a/test/asan/TestCases/Linux/local_alias.cc
+++ b/test/asan/TestCases/Linux/local_alias.cc
@@ -6,7 +6,10 @@
//
// FIXME: https://github.com/google/sanitizers/issues/316
// XFAIL: android
-// XFAIL: mips64
+//
+// This test requires the integrated assembler to be the default.
+// XFAIL: target-is-mips64
+// XFAIL: target-is-mips64el
//
// RUN: %clangxx_asan -DBUILD_INSTRUMENTED_DSO=1 -fPIC -shared -mllvm -asan-use-private-alias %s -o %t-INSTRUMENTED-SO.so
// RUN: %clangxx -DBUILD_UNINSTRUMENTED_DSO=1 -fPIC -shared %s -o %t-UNINSTRUMENTED-SO.so
diff --git a/test/asan/TestCases/Linux/malloc_delete_mismatch.cc b/test/asan/TestCases/Linux/malloc_delete_mismatch.cc
index 66eed33052c3b..50d920e43f38f 100644
--- a/test/asan/TestCases/Linux/malloc_delete_mismatch.cc
+++ b/test/asan/TestCases/Linux/malloc_delete_mismatch.cc
@@ -12,8 +12,7 @@
// Also works if no malloc context is available.
// RUN: %env_asan_opts=alloc_dealloc_mismatch=1:malloc_context_size=0:fast_unwind_on_malloc=0 not %run %t 2>&1 | FileCheck %s
// RUN: %env_asan_opts=alloc_dealloc_mismatch=1:malloc_context_size=0:fast_unwind_on_malloc=1 not %run %t 2>&1 | FileCheck %s
-// XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
+// REQUIRES: stable-runtime
#include <stdlib.h>
static volatile char *x;
diff --git a/test/asan/TestCases/Linux/memmem_test.cc b/test/asan/TestCases/Linux/memmem_test.cc
index 54883004e0aa6..661381cdd7b7f 100644
--- a/test/asan/TestCases/Linux/memmem_test.cc
+++ b/test/asan/TestCases/Linux/memmem_test.cc
@@ -1,6 +1,6 @@
// RUN: %clangxx_asan %s -o %t
-// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=A1
-// RUN: not %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=A2
+// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=A1
+// RUN: not %run %t 1 2>&1 | FileCheck %s --check-prefix=A2
// RUN: %env_asan_opts=intercept_memmem=0 %run %t
#include <string.h>
@@ -12,10 +12,13 @@ int main(int argc, char **argv) {
res = memmem(a1, sizeof(a1) + 1, a2, sizeof(a2)); // BOOM
else
res = memmem(a1, sizeof(a1), a2, sizeof(a2) + 1); // BOOM
- // CHECK: AddressSanitizer: stack-buffer-overflow
- // CHECK: {{#0.*memmem}}
- // CHECK: {{#1.*main}}
+ // A1: AddressSanitizer: stack-buffer-overflow
+ // A1: {{#0.*memmem}}
+ // A1-NEXT: {{#1.*main}}
// A1: 'a1' <== Memory access at offset
+ //
+ // A2: AddressSanitizer: stack-buffer-overflow
+ // A2: {{#0.*memmem}}
// A2: 'a2' <== Memory access at offset
return res == NULL;
}
diff --git a/test/asan/TestCases/Linux/new_delete_mismatch.cc b/test/asan/TestCases/Linux/new_delete_mismatch.cc
index 1cfc0ef053127..3a71862fb732e 100644
--- a/test/asan/TestCases/Linux/new_delete_mismatch.cc
+++ b/test/asan/TestCases/Linux/new_delete_mismatch.cc
@@ -1,8 +1,8 @@
// Check that we report new[] vs delete as alloc-dealloc-mismatch and not as
// new-delete-type-mismatch when -fsized-deallocation is enabled.
-// RUN: %clangxx_asan -g %s -o %t && not %run %t |& FileCheck %s
-// RUN: %clangxx_asan -fsized-deallocation -g %s -o %t && not %run %t |& FileCheck %s
+// RUN: %clangxx_asan -g %s -o %t && %env_asan_opts=alloc_dealloc_mismatch=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -fsized-deallocation -g %s -o %t && %env_asan_opts=alloc_dealloc_mismatch=1 not %run %t 2>&1 | FileCheck %s
#include <stdlib.h>
diff --git a/test/asan/TestCases/Linux/odr-violation.cc b/test/asan/TestCases/Linux/odr-violation.cc
index 143fb6e14344f..d909143a86a13 100644
--- a/test/asan/TestCases/Linux/odr-violation.cc
+++ b/test/asan/TestCases/Linux/odr-violation.cc
@@ -1,6 +1,9 @@
// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
// XFAIL: android
-// XFAIL: mips64
+//
+// This test requires the integrated assembler to be the default.
+// XFAIL: target-is-mips64
+// XFAIL: target-is-mips64el
//
// We use fast_unwind_on_malloc=0 to have full unwinding even w/o frame
// pointers. This setting is not on by default because it's too expensive.
diff --git a/test/asan/TestCases/Linux/print_memory_profile_test.cc b/test/asan/TestCases/Linux/print_memory_profile_test.cc
index d30dbea1cf6d1..8909ccad08d46 100644
--- a/test/asan/TestCases/Linux/print_memory_profile_test.cc
+++ b/test/asan/TestCases/Linux/print_memory_profile_test.cc
@@ -3,27 +3,31 @@
// REQUIRES: leak-detection
//
// RUN: %clangxx_asan %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
+// RUN: %run %t 100 2>&1 | FileCheck %s --check-prefix=CHECK-100
+// RUN: %run %t 50 2>&1 | FileCheck %s --check-prefix=CHECK-50
#include <sanitizer/common_interface_defs.h>
#include <stdio.h>
+#include <stdlib.h>
char *sink[1000];
-int main() {
+int main(int argc, char **argv) {
+ if (argc < 2)
+ return 1;
+
int idx = 0;
for (int i = 0; i < 17; i++)
sink[idx++] = new char[131000];
for (int i = 0; i < 28; i++)
sink[idx++] = new char[24000];
- __sanitizer_print_memory_profile(100);
- __sanitizer_print_memory_profile(50);
+ __sanitizer_print_memory_profile(atoi(argv[1]));
}
-// CHECK: Live Heap Allocations: {{.*}}; showing top 100%
-// CHECK: 2227000 byte(s) ({{.*}}%) in 17 allocation(s)
-// CHECK: 672000 byte(s) ({{.*}}%) in 28 allocation(s)
-// CHECK: Live Heap Allocations: {{.*}}; showing top 50%
-// CHECK: 2227000 byte(s) ({{.*}}%) in 17 allocation(s)
-// CHECK-NOT: 1008 byte
+// CHECK-100: Live Heap Allocations: {{.*}}; showing top 100%
+// CHECK-100: 2227000 byte(s) ({{.*}}%) in 17 allocation(s)
+// CHECK-100: 672000 byte(s) ({{.*}}%) in 28 allocation(s)
+// CHECK-50: Live Heap Allocations: {{.*}}; showing top 50%
+// CHECK-50: 2227000 byte(s) ({{.*}}%) in 17 allocation(s)
+// CHECK-50-NOT: allocation
diff --git a/test/asan/TestCases/Linux/pthread_create_from_constructor.cc b/test/asan/TestCases/Linux/pthread_create_from_constructor.cc
new file mode 100644
index 0000000000000..8f9b0b4fed1a5
--- /dev/null
+++ b/test/asan/TestCases/Linux/pthread_create_from_constructor.cc
@@ -0,0 +1,49 @@
+// Test that ASan doesn't deadlock in __interceptor_pthread_create called
+// from dlopened shared library constructor. The deadlock happens only in shared
+// ASan runtime with recent Glibc (2.23 fits) when __interceptor_pthread_create
+// grabs global Glibc's GL(dl_load_lock) and waits for tls_get_addr_tail that
+// also tries to acquire it.
+//
+// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t-so.so
+// RUN: %clangxx_asan %s -o %t
+// RUN: %run %t 2>&1
+
+// dlopen() can not be intercepted on Android
+// UNSUPPORTED: android
+// REQUIRES: x86-target-arch
+
+#ifdef BUILD_SO
+
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+
+void *threadFn(void *) {
+ fprintf(stderr, "thread started\n");
+ while (true) {
+ usleep(100000);
+ }
+ return 0;
+}
+
+void __attribute__((constructor)) startPolling() {
+ fprintf(stderr, "initializing library\n");
+ pthread_t t;
+ pthread_create(&t, 0, &threadFn, 0);
+ fprintf(stderr, "done\n");
+}
+
+#else
+
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <string>
+
+int main(int argc, char **argv) {
+ std::string path = std::string(argv[0]) + "-so.so";
+ void *handle = dlopen(path.c_str(), RTLD_LAZY);
+ if (!handle)
+ abort();
+ return 0;
+}
+#endif
diff --git a/test/asan/TestCases/Linux/quarantine_size_mb.cc b/test/asan/TestCases/Linux/quarantine_size_mb.cc
index cbacec22fa1ea..239eeabee1707 100644
--- a/test/asan/TestCases/Linux/quarantine_size_mb.cc
+++ b/test/asan/TestCases/Linux/quarantine_size_mb.cc
@@ -4,7 +4,7 @@
// RUN: %env_asan_opts=quarantine_size_mb=10:verbosity=1:hard_rss_limit_mb=50 %run %t 2>&1 | FileCheck %s --check-prefix=Q10
// RUN: %env_asan_opts=quarantine_size_mb=10:quarantine_size=20:verbosity=1 not %run %t 2>&1 | FileCheck %s --check-prefix=BOTH
// RUN: %env_asan_opts=quarantine_size_mb=1000:hard_rss_limit_mb=50 not %run %t 2>&1 | FileCheck %s --check-prefix=RSS_LIMIT
-// RUN: %env_asan_opts=hard_rss_limit_mb=50 not %run %t 2>&1 | FileCheck %s --check-prefix=RSS_LIMIT
+// RUN: %env_asan_opts=hard_rss_limit_mb=20 not %run %t 2>&1 | FileCheck %s --check-prefix=RSS_LIMIT
#include <string.h>
char *g;
diff --git a/test/asan/TestCases/Linux/release_to_os_test.cc b/test/asan/TestCases/Linux/release_to_os_test.cc
new file mode 100644
index 0000000000000..26402167d6b11
--- /dev/null
+++ b/test/asan/TestCases/Linux/release_to_os_test.cc
@@ -0,0 +1,46 @@
+// Tests ASAN_OPTIONS=allocator_release_to_os=1
+//
+
+// RUN: %clangxx_asan -std=c++11 %s -o %t
+// RUN: %env_asan_opts=allocator_release_to_os_interval_ms=0 %run %t 2>&1 | FileCheck %s --check-prefix=RELEASE
+// RUN: %env_asan_opts=allocator_release_to_os_interval_ms=-1 %run %t 2>&1 | FileCheck %s --check-prefix=NO_RELEASE
+//
+// REQUIRES: x86_64-target-arch
+#include <stdlib.h>
+#include <stdio.h>
+#include <algorithm>
+#include <stdint.h>
+#include <assert.h>
+
+#include <sanitizer/asan_interface.h>
+
+void MallocReleaseStress() {
+ const size_t kNumChunks = 10000;
+ const size_t kAllocSize = 100;
+ const size_t kNumIter = 100;
+ uintptr_t *chunks[kNumChunks] = {0};
+
+ for (size_t iter = 0; iter < kNumIter; iter++) {
+ std::random_shuffle(chunks, chunks + kNumChunks);
+ size_t to_replace = rand() % kNumChunks;
+ for (size_t i = 0; i < kNumChunks; i++) {
+ if (chunks[i])
+ assert(chunks[i][0] == (uintptr_t)chunks[i]);
+ if (i < to_replace) {
+ delete [] chunks[i];
+ chunks[i] = new uintptr_t[kAllocSize];
+ chunks[i][0] = (uintptr_t)chunks[i];
+ }
+ }
+ }
+ for (auto p : chunks)
+ delete[] p;
+}
+
+int main() {
+ MallocReleaseStress();
+ __asan_print_accumulated_stats();
+}
+
+// RELEASE: mapped:{{.*}}releases: {{[1-9]}}
+// NO_RELEASE: mapped:{{.*}}releases: 0
diff --git a/test/asan/TestCases/Linux/stack-trace-dlclose.cc b/test/asan/TestCases/Linux/stack-trace-dlclose.cc
index 49c2089780108..e604f1e4f73f6 100644
--- a/test/asan/TestCases/Linux/stack-trace-dlclose.cc
+++ b/test/asan/TestCases/Linux/stack-trace-dlclose.cc
@@ -4,8 +4,7 @@
// RUN: %clangxx_asan -DSHARED %s -shared -o %T/stack_trace_dlclose.so -fPIC
// RUN: %clangxx_asan -DSO_DIR=\"%T\" %s %libdl -o %t
// RUN: %env_asan_opts=exitcode=0 %run %t 2>&1 | FileCheck %s
-// XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
+// REQUIRES: stable-runtime
#include <assert.h>
#include <dlfcn.h>
diff --git a/test/asan/TestCases/Linux/swapcontext_annotation.cc b/test/asan/TestCases/Linux/swapcontext_annotation.cc
index 90aabaee205bb..56e811942b880 100644
--- a/test/asan/TestCases/Linux/swapcontext_annotation.cc
+++ b/test/asan/TestCases/Linux/swapcontext_annotation.cc
@@ -1,12 +1,17 @@
// Check that ASan plays well with annotated makecontext/swapcontext.
-// RUN: %clangxx_asan -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_asan -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_asan -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_asan -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -std=c++11 -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -std=c++11 -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -std=c++11 -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -std=c++11 -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -std=c++11 -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK
+// RUN: %clangxx_asan -std=c++11 -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK
+// RUN: %clangxx_asan -std=c++11 -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK
+// RUN: %clangxx_asan -std=c++11 -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK
+
//
// This test is too subtle to try on non-x86 arch for now.
-// REQUIRES: x86_64-supported-target,i386-supported-target
+// REQUIRES: x86-target-arch
#include <pthread.h>
#include <setjmp.h>
@@ -25,9 +30,12 @@ char *next_child_stack;
const int kStackSize = 1 << 20;
-void *main_thread_stack;
+const void *main_thread_stack;
size_t main_thread_stacksize;
+const void *from_stack;
+size_t from_stacksize;
+
__attribute__((noinline, noreturn)) void LongJump(jmp_buf env) {
longjmp(env, 1);
_exit(1);
@@ -44,14 +52,18 @@ __attribute__((noinline)) void CallNoReturn() {
void NextChild() {
CallNoReturn();
- __sanitizer_finish_switch_fiber();
+ __sanitizer_finish_switch_fiber(nullptr, &from_stack, &from_stacksize);
+
+ printf("NextChild from: %p %zu\n", from_stack, from_stacksize);
char x[32] = {0}; // Stack gets poisoned.
printf("NextChild: %p\n", x);
CallNoReturn();
- __sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize);
+ __sanitizer_start_switch_fiber(nullptr,
+ main_thread_stack,
+ main_thread_stacksize);
CallNoReturn();
if (swapcontext(&next_child_context, &orig_context) < 0) {
perror("swapcontext");
@@ -61,7 +73,9 @@ void NextChild() {
void Child(int mode) {
CallNoReturn();
- __sanitizer_finish_switch_fiber();
+ __sanitizer_finish_switch_fiber(nullptr,
+ &main_thread_stack,
+ &main_thread_stacksize);
char x[32] = {0}; // Stack gets poisoned.
printf("Child: %p\n", x);
CallNoReturn();
@@ -70,21 +84,28 @@ void Child(int mode) {
// something.
// (c) Jump to another function which will then jump back to the main function
if (mode == 0) {
- __sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize);
+ __sanitizer_start_switch_fiber(nullptr,
+ main_thread_stack,
+ main_thread_stacksize);
CallNoReturn();
} else if (mode == 1) {
- __sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize);
+ __sanitizer_start_switch_fiber(nullptr,
+ main_thread_stack,
+ main_thread_stacksize);
CallNoReturn();
if (swapcontext(&child_context, &orig_context) < 0) {
perror("swapcontext");
_exit(1);
}
} else if (mode == 2) {
+ printf("NextChild stack: %p\n", next_child_stack);
+
getcontext(&next_child_context);
next_child_context.uc_stack.ss_sp = next_child_stack;
next_child_context.uc_stack.ss_size = kStackSize / 2;
makecontext(&next_child_context, (void (*)())NextChild, 0);
- __sanitizer_start_switch_fiber(next_child_context.uc_stack.ss_sp,
+ __sanitizer_start_switch_fiber(nullptr,
+ next_child_context.uc_stack.ss_sp,
next_child_context.uc_stack.ss_size);
CallNoReturn();
if (swapcontext(&child_context, &next_child_context) < 0) {
@@ -105,7 +126,9 @@ int Run(int arg, int mode, char *child_stack) {
}
makecontext(&child_context, (void (*)())Child, 1, mode);
CallNoReturn();
- __sanitizer_start_switch_fiber(child_context.uc_stack.ss_sp,
+ void* fake_stack_save;
+ __sanitizer_start_switch_fiber(&fake_stack_save,
+ child_context.uc_stack.ss_sp,
child_context.uc_stack.ss_size);
CallNoReturn();
if (swapcontext(&orig_context, &child_context) < 0) {
@@ -113,8 +136,11 @@ int Run(int arg, int mode, char *child_stack) {
_exit(1);
}
CallNoReturn();
- __sanitizer_finish_switch_fiber();
+ __sanitizer_finish_switch_fiber(fake_stack_save,
+ &from_stack,
+ &from_stacksize);
CallNoReturn();
+ printf("Main context from: %p %zu\n", from_stack, from_stacksize);
// Touch childs's stack to make sure it's unpoisoned.
for (int i = 0; i < kStackSize; i++) {
@@ -125,17 +151,7 @@ int Run(int arg, int mode, char *child_stack) {
void handler(int sig) { CallNoReturn(); }
-void InitStackBounds() {
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_getattr_np(pthread_self(), &attr);
- pthread_attr_getstack(&attr, &main_thread_stack, &main_thread_stacksize);
- pthread_attr_destroy(&attr);
-}
-
int main(int argc, char **argv) {
- InitStackBounds();
-
// set up a signal that will spam and trigger __asan_handle_no_return at
// tricky moments
struct sigaction act = {};
@@ -162,12 +178,22 @@ int main(int argc, char **argv) {
// CHECK-NOT: ASan is ignoring requested __asan_handle_no_return
for (unsigned int i = 0; i < 30; ++i) {
ret += Run(argc - 1, 0, stack);
+ // LOOPCHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]]
+ // LOOPCHECK: Main context from: [[CHILD_STACK]] 524288
ret += Run(argc - 1, 1, stack);
+ // LOOPCHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]]
+ // LOOPCHECK: Main context from: [[CHILD_STACK]] 524288
ret += Run(argc - 1, 2, stack);
+ // LOOPCHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]]
+ // LOOPCHECK: NextChild stack: [[NEXT_CHILD_STACK:0x[0-9a-f]*]]
+ // LOOPCHECK: NextChild from: [[CHILD_STACK]] 524288
+ // LOOPCHECK: Main context from: [[NEXT_CHILD_STACK]] 524288
ret += Run(argc - 1, 0, heap);
ret += Run(argc - 1, 1, heap);
ret += Run(argc - 1, 2, heap);
+ printf("Iteration %d passed\n", i);
}
+
// CHECK: Test passed
printf("Test passed\n");
diff --git a/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc b/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc
new file mode 100644
index 0000000000000..7176484ed21ce
--- /dev/null
+++ b/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc
@@ -0,0 +1,40 @@
+// Test thread_local_quarantine_size_kb
+
+// RUN: %clangxx_asan %s -o %t
+// RUN: %env_asan_opts=thread_local_quarantine_size_kb=256:verbosity=1 %run %t 2>&1 | \
+// RUN: FileCheck %s --check-prefix=CHECK-VALUE
+// RUN: %env_asan_opts=thread_local_quarantine_size_kb=64:quarantine_size_mb=64 %run %t 2>&1 | \
+// RUN: FileCheck %s --allow-empty --check-prefix=CHECK-SMALL-LOCAL-CACHE-SMALL-OVERHEAD
+// RUN: %env_asan_opts=thread_local_quarantine_size_kb=0:quarantine_size_mb=64 %run %t 2>&1 | \
+// RUN: FileCheck %s --check-prefix=CHECK-NO-LOCAL-CACHE-HUGE-OVERHEAD
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sanitizer/allocator_interface.h>
+
+// The idea is allocate a lot of small blocks, totaling 5Mb of user memory
+// total, and verify that quarantine does not incur too much memory overhead.
+// There's always an overhead for red zones, shadow memory and such, but
+// quarantine accounting should not significantly contribute to that.
+static const int kNumAllocs = 20000;
+static const int kAllocSize = 256;
+static const size_t kHeapSizeLimit = 12 << 20;
+
+int main() {
+ size_t old_heap_size = __sanitizer_get_heap_size();
+ for (int i = 0; i < kNumAllocs; i++) {
+ char *g = new char[kAllocSize];
+ memset(g, -1, kAllocSize);
+ delete [] (g);
+ }
+ size_t new_heap_size = __sanitizer_get_heap_size();
+ fprintf(stderr, "heap size: new: %zd old: %zd\n", new_heap_size,
+ old_heap_size);
+ if (new_heap_size - old_heap_size > kHeapSizeLimit)
+ fprintf(stderr, "Heap size limit exceeded");
+}
+
+// CHECK-VALUE: thread_local_quarantine_size_kb=256K
+// CHECK-SMALL-LOCAL-CACHE-SMALL-OVERHEAD-NOT: Heap size limit exceeded
+// CHECK-NO-LOCAL-CACHE-HUGE-OVERHEAD: Heap size limit exceeded
diff --git a/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc b/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc
index dd59e4a60774a..cb9ca53e8a9af 100644
--- a/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc
+++ b/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc
@@ -7,8 +7,8 @@
// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
// RUN: %clangxx_asan -O0 %s %libdl -o %t
// RUN: %env_asan_opts=symbolize=0 not %run %t 2>&1 | %asan_symbolize | FileCheck %s
-// XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
+// UNSUPPORTED: x86_64h-darwin,x86_64-darwin
+// REQUIRES: stable-runtime
#if !defined(SHARED_LIB)
#include <dlfcn.h>
diff --git a/test/asan/TestCases/Posix/coverage-fork.cc b/test/asan/TestCases/Posix/coverage-fork.cc
index 799d71638a26e..40ce72ef5003b 100644
--- a/test/asan/TestCases/Posix/coverage-fork.cc
+++ b/test/asan/TestCases/Posix/coverage-fork.cc
@@ -3,7 +3,7 @@
// RUN: mkdir -p %T/coverage-fork && cd %T/coverage-fork
// RUN: %env_asan_opts=coverage=1:coverage_direct=0:verbosity=1 %run %t 2>&1 | FileCheck %s
//
-// XFAIL: android
+// UNSUPPORTED: android
#include <stdio.h>
#include <string.h>
diff --git a/test/asan/TestCases/Posix/halt_on_error-signals.c b/test/asan/TestCases/Posix/halt_on_error-signals.c
index 60916f6570fcb..6bdf30bb4dd3e 100644
--- a/test/asan/TestCases/Posix/halt_on_error-signals.c
+++ b/test/asan/TestCases/Posix/halt_on_error-signals.c
@@ -3,7 +3,7 @@
// RUN: %clang_asan -fsanitize-recover=address -pthread %s -o %t
//
// RUN: rm -f %t.log
-// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 100 >%t.log 2>&1 || true
+// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 100 >>%t.log 2>&1 || true
// Collision will almost always get triggered but we still need to check the unlikely case:
// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < %t.log || FileCheck --check-prefix=CHECK-NO-COLLISION %s < %t.log
diff --git a/test/asan/TestCases/Posix/halt_on_error-torture.cc b/test/asan/TestCases/Posix/halt_on_error-torture.cc
index d3af1d0277035..5d7eff06e34e6 100644
--- a/test/asan/TestCases/Posix/halt_on_error-torture.cc
+++ b/test/asan/TestCases/Posix/halt_on_error-torture.cc
@@ -2,18 +2,21 @@
//
// RUN: %clangxx_asan -fsanitize-recover=address -pthread %s -o %t
//
-// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 1 10 >1.txt 2>&1
+// RUN: rm -f 1.txt
+// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 1 10 >>1.txt 2>&1
// RUN: FileCheck %s < 1.txt
// RUN: [ $(grep -c 'ERROR: AddressSanitizer: use-after-poison' 1.txt) -eq 10 ]
// RUN: FileCheck --check-prefix=CHECK-NO-COLLISION %s < 1.txt
//
// Collisions are unlikely but still possible so we need the ||.
-// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 10 20 >10.txt 2>&1 || true
+// RUN: rm -f 10.txt
+// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 10 20 >>10.txt 2>&1 || true
// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 10.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 10.txt
//
// Collisions are unlikely but still possible so we need the ||.
-// RUN: %env_asan_opts=halt_on_error=false %run %t 10 20 >10.txt 2>&1 || true
-// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 10.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 10.txt
+// RUN: rm -f 20.txt
+// RUN: %env_asan_opts=halt_on_error=false %run %t 10 20 >>20.txt 2>&1 || true
+// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 20.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 20.txt
#include <stdio.h>
#include <stdlib.h>
diff --git a/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc b/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc
index 98b034812ef63..98ef851657b7d 100644
--- a/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc
+++ b/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc
@@ -6,14 +6,16 @@
// RUN: %env_asan_opts=halt_on_error=false %run %t 2>&1 | FileCheck %s
//
// Check that we die after reaching different reports number threshold.
-// RUN: %env_asan_opts=halt_on_error=false not %run %t 1 > %t1.log 2>&1
+// RUN: rm -f %t1.log
+// RUN: %env_asan_opts=halt_on_error=false not %run %t 1 >> %t1.log 2>&1
// RUN: [ $(grep -c 'ERROR: AddressSanitizer: stack-buffer-overflow' %t1.log) -eq 25 ]
//
// Check suppress_equal_pcs=true behavior is equal to default one.
// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=true %run %t 2>&1 | FileCheck %s
//
// Check suppress_equal_pcs=false behavior isn't equal to default one.
-// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t > %t2.log 2>&1
+// RUN: rm -f %t2.log
+// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t >> %t2.log 2>&1
// RUN: [ $(grep -c 'ERROR: AddressSanitizer: stack-buffer-overflow' %t2.log) -eq 30 ]
#define ACCESS_ARRAY_FIVE_ELEMENTS(array, i) \
diff --git a/test/asan/TestCases/Posix/handle_abort_on_error.cc b/test/asan/TestCases/Posix/handle_abort_on_error.cc
new file mode 100644
index 0000000000000..fa8cdd4ce0c86
--- /dev/null
+++ b/test/asan/TestCases/Posix/handle_abort_on_error.cc
@@ -0,0 +1,9 @@
+// Regression test: this used to abort() in SIGABRT handler in an infinite loop.
+// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=handle_abort=1,abort_on_error=1 not --crash %run %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+
+int main() {
+ abort();
+ // CHECK: ERROR: AddressSanitizer: ABRT
+}
diff --git a/test/asan/TestCases/no_asan_gen_globals.c b/test/asan/TestCases/Posix/no_asan_gen_globals.c
index 2b13deace4b5f..c686f83ac4a89 100644
--- a/test/asan/TestCases/no_asan_gen_globals.c
+++ b/test/asan/TestCases/Posix/no_asan_gen_globals.c
@@ -2,7 +2,6 @@
// XFAIL: android
// FIXME: http://llvm.org/bugs/show_bug.cgi?id=22682
// REQUIRES: asan-64-bits
-//
// Make sure __asan_gen_* strings do not end up in the symbol table.
// RUN: %clang_asan %s -o %t.exe
diff --git a/test/asan/TestCases/Posix/start-deactivated.cc b/test/asan/TestCases/Posix/start-deactivated.cc
index 187ee5e549efe..9691404ebcea9 100644
--- a/test/asan/TestCases/Posix/start-deactivated.cc
+++ b/test/asan/TestCases/Posix/start-deactivated.cc
@@ -2,8 +2,8 @@
// Main executable is uninstrumented, but linked to ASan runtime. The shared
// library is instrumented. Memory errors before dlopen are not detected.
-// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
-// RUN: %clangxx -O0 %s -c -o %t.o
+// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -std=c++11 -fPIC -shared -o %t-so.so
+// RUN: %clangxx -O0 %s -std=c++11 -c -o %t.o
// RUN: %clangxx_asan -O0 %t.o %libdl -o %t
// RUN: %env_asan_opts=start_deactivated=1,allocator_may_return_null=0 \
// RUN: ASAN_ACTIVATION_OPTIONS=allocator_may_return_null=1 not %run %t 2>&1 | FileCheck %s
@@ -32,18 +32,25 @@
#include "sanitizer/asan_interface.h"
-void test_malloc_shadow() {
- char *p = (char *)malloc(100);
- char *q = (char *)__asan_region_is_poisoned(p + 95, 8);
- fprintf(stderr, "=%zd=\n", q ? q - (p + 95) : -1);
- free(p);
+constexpr unsigned nPtrs = 200;
+char *ptrs[nPtrs];
+
+void test_malloc_shadow(char *p, size_t sz, bool expect_redzones) {
+ assert((char *)__asan_region_is_poisoned(p - 1, sz + 1) ==
+ (expect_redzones ? p - 1 : nullptr));
+ assert((char *)__asan_region_is_poisoned(p, sz) == nullptr);
+ assert((char *)__asan_region_is_poisoned(p, sz + 1) ==
+ (expect_redzones ? p + sz : nullptr));
}
typedef void (*Fn)();
int main(int argc, char *argv[]) {
- test_malloc_shadow();
- // CHECK: =-1=
+ // Before activation: no redzones.
+ for (size_t sz = 1; sz < nPtrs; ++sz) {
+ ptrs[sz] = (char *)malloc(sz);
+ test_malloc_shadow(ptrs[sz], sz, false);
+ }
std::string path = std::string(argv[0]) + "-so.so";
void *dso = dlopen(path.c_str(), RTLD_NOW);
@@ -52,9 +59,6 @@ int main(int argc, char *argv[]) {
return 1;
}
- test_malloc_shadow();
- // CHECK: =5=
-
// After this line ASan is activated and starts detecting errors.
void *fn = dlsym(dso, "do_another_bad_thing");
if (!fn) {
@@ -62,6 +66,19 @@ int main(int argc, char *argv[]) {
return 1;
}
+ // After activation: redzones.
+ {
+ char *p = (char *)malloc(100);
+ test_malloc_shadow(p, 100, true);
+ free(p);
+ }
+
+ // Pre-existing allocations got redzones, too.
+ for (size_t sz = 1; sz < nPtrs; ++sz) {
+ test_malloc_shadow(ptrs[sz], sz, true);
+ free(ptrs[sz]);
+ }
+
// Test that ASAN_ACTIVATION_OPTIONS=allocator_may_return_null=1 has effect.
void *p = malloc((unsigned long)-2);
assert(!p);
diff --git a/test/asan/TestCases/Windows/bind_io_completion_callback.cc b/test/asan/TestCases/Windows/bind_io_completion_callback.cc
index 44b92ab914655..ef7e45867ede0 100644
--- a/test/asan/TestCases/Windows/bind_io_completion_callback.cc
+++ b/test/asan/TestCases/Windows/bind_io_completion_callback.cc
@@ -1,11 +1,6 @@
// Make sure we can throw exceptions from work items executed via
// BindIoCompletionCallback.
//
-// Clang doesn't support exceptions on Windows yet, so for the time being we
-// build this program in two parts: the code with exceptions is built with CL,
-// the rest is built with Clang. This represents the typical scenario when we
-// build a large project using "clang-cl -fallback -fsanitize=address".
-//
// RUN: %clangxx_asan %s -o %t.exe
// RUN: %run %t.exe 2>&1 | FileCheck %s
diff --git a/test/asan/TestCases/Windows/coverage-dll-stdio.cc b/test/asan/TestCases/Windows/coverage-dll-stdio.cc
new file mode 100644
index 0000000000000..5e12e38554499
--- /dev/null
+++ b/test/asan/TestCases/Windows/coverage-dll-stdio.cc
@@ -0,0 +1,16 @@
+// Test that coverage and MSVC CRT stdio work from a DLL. This ensures that the
+// __local_stdio_printf_options function isn't instrumented for coverage.
+
+// RUN: rm -rf %t && mkdir %t && cd %t
+// RUN: %clang_cl_asan -fsanitize-coverage=func -O0 %p/dll_host.cc -Fet.exe
+// RUN: %clang_cl_asan -fsanitize-coverage=func -LD -O0 %s -Fet.dll
+// RUN: %run ./t.exe t.dll 2>&1 | FileCheck %s
+
+#include <stdio.h>
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ printf("hello world\n");
+ // CHECK: hello world
+ return 0;
+}
diff --git a/test/asan/TestCases/Windows/default_options.cc b/test/asan/TestCases/Windows/default_options.cc
deleted file mode 100644
index 6e0a28f336926..0000000000000
--- a/test/asan/TestCases/Windows/default_options.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %clangxx_asan -O2 %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
-
-// FIXME: merge this with the common default_options test when we can run common
-// tests on Windows.
-
-const char *kAsanDefaultOptions="verbosity=1 help=1";
-
-extern "C"
-__attribute__((no_sanitize_address))
-const char *__asan_default_options() {
- // CHECK: Available flags for AddressSanitizer:
- return kAsanDefaultOptions;
-}
-
-int main() {
- return 0;
-}
diff --git a/test/asan/TestCases/Windows/delay_dbghelp.cc b/test/asan/TestCases/Windows/delay_dbghelp.cc
new file mode 100644
index 0000000000000..81cd2d389c3b4
--- /dev/null
+++ b/test/asan/TestCases/Windows/delay_dbghelp.cc
@@ -0,0 +1,18 @@
+// Build an executable with ASan, then extract the DLLs that it depends on.
+// RUN: %clang_cl_asan %s -Fe%t.exe
+// RUN: llvm-readobj -coff-imports %t.exe | grep Name: | sed -e 's/ *Name: *//' > %t
+//
+// Make sure the binary doesn't depend on dbghelp directly.
+// RUN: not grep dbghelp.dll %t
+//
+// Make sure any clang_rt DLLs it depends on don't depend on dbghelp. In the
+// static build, there won't be any clang_rt DLLs.
+// RUN: not grep cl""ang_rt %t || \
+// RUN: grep cl""ang_rt %t | xargs which | \
+// RUN: xargs llvm-readobj -coff-imports | not grep dbghelp.dll %t
+
+extern "C" int puts(const char *);
+
+int main() {
+ puts("main");
+}
diff --git a/test/asan/TestCases/Windows/dll_global_dead_strip.c b/test/asan/TestCases/Windows/dll_global_dead_strip.c
new file mode 100644
index 0000000000000..2664f5baff6c0
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_global_dead_strip.c
@@ -0,0 +1,28 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+//
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: %env_asan_opts=report_globals=2 %run %t %t.dll 2>&1 | FileCheck %s --check-prefix=NOSTRIP
+// RUN: %clang_cl_asan -LD -O2 %s -Fe%t.dll -link -opt:ref
+// RUN: %env_asan_opts=report_globals=2 %run %t %t.dll 2>&1 | FileCheck %s --check-prefix=STRIP
+
+#include <stdio.h>
+
+int dead_global = 42;
+int live_global = 0;
+
+__declspec(dllexport)
+int test_function() {
+ puts("main");
+ return live_global;
+}
+
+// Check that our global registration scheme works with MSVC's linker dead
+// stripping (/OPT:REF).
+
+// NOSTRIP: Added Global{{.*}}name=dead_global
+// NOSTRIP: Added Global{{.*}}name=live_global
+// NOSTRIP: main
+
+// STRIP-NOT: Added Global{{.*}}name=dead_global
+// STRIP: Added Global{{.*}}name=live_global
+// STRIP: main
diff --git a/test/asan/TestCases/Windows/dll_host.cc b/test/asan/TestCases/Windows/dll_host.cc
index 71721fe29e888..6a029c96d4d8c 100644
--- a/test/asan/TestCases/Windows/dll_host.cc
+++ b/test/asan/TestCases/Windows/dll_host.cc
@@ -5,20 +5,41 @@
// RUN: %clang_cl_asan -O0 %s -Fe%t
//
// Get the list of ASan wrappers exported by the main module RTL:
-// RUN: dumpbin /EXPORTS %t | grep -o "__asan_wrap[^ ]*" | grep -v @ | sort | uniq > %t.exported_wrappers
+// note: The mangling decoration (i.e. @4 )is removed because calling convention
+// differ from 32-bit and 64-bit.
+// RUN: dumpbin /EXPORTS %t | grep -o "__asan_wrap[^ ]*" | sed -e s/@.*// > %t.exported_wrappers1
// FIXME: we should really check the other __asan exports too.
-// RUN: dumpbin /EXPORTS %t | grep -o "__sanitizer_[^ ]*" | grep -v @ | sort | uniq >> %t.exported_wrappers
+// RUN: dumpbin /EXPORTS %t | grep -o "__sanitizer_[^ ]*" | sed -e s/@.*// > %t.exported_wrappers2
//
// Get the list of ASan wrappers imported by the DLL RTL:
// [BEWARE: be really careful with the sed commands, as this test can be run
// from different environemnts with different shells and seds]
-// RUN: grep INTERCEPT_LIBRARY_FUNCTION %p/../../../../lib/asan/asan_win_dll_thunk.cc | grep -v define | sed -e s/.*(/__asan_wrap_/ | sed -e s/).*// | sort | uniq > %t.dll_imports
-// RUN: grep "^INTERFACE_FUNCTION.*sanitizer" %p/../../../../lib/asan/asan_win_dll_thunk.cc | grep -v define | sed -e s/.*(// | sed -e s/).*// | sort | uniq >> %t.dll_imports
+// RUN: grep INTERCEPT_LIBRARY_FUNCTION %p/../../../../lib/asan/asan_win_dll_thunk.cc | grep -v define | sed -e s/.*(/__asan_wrap_/ | sed -e s/).*// > %t.dll_imports1
+// RUN: grep "^INTERFACE_FUNCTION.*sanitizer" %p/../../../../lib/asan/asan_win_dll_thunk.cc | grep -v define | sed -e s/.*(// | sed -e s/).*// > %t.dll_imports2
+//
+// Add functions interecepted in asan_malloc.win.cc and asan_win.cc.
+// RUN: grep '[I]MPORT:' %s | sed -e 's/.*[I]MPORT: //' > %t.dll_imports3
+// IMPORT: __asan_wrap_HeapAlloc
+// IMPORT: __asan_wrap_HeapFree
+// IMPORT: __asan_wrap_HeapReAlloc
+// IMPORT: __asan_wrap_HeapSize
+// IMPORT: __asan_wrap_CreateThread
+// IMPORT: __asan_wrap_RaiseException
+// IMPORT: __asan_wrap_RtlRaiseException
+//
+// The exception handlers differ in 32-bit and 64-bit, so we ignore them:
+// RUN: grep '[E]XPORT:' %s | sed -e 's/.*[E]XPORT: //' > %t.exported_wrappers3
+// EXPORT: __asan_wrap__except_handler3
+// EXPORT: __asan_wrap__except_handler4
+// EXPORT: __asan_wrap___C_specific_handler
+//
+// RUN: cat %t.dll_imports1 %t.dll_imports2 %t.dll_imports3 | sort | uniq > %t.dll_imports-sorted
+// RUN: cat %t.exported_wrappers1 %t.exported_wrappers2 %t.exported_wrappers3 | sort | uniq > %t.exported_wrappers-sorted
//
// Now make sure the DLL thunk imports everything:
// RUN: echo
// RUN: echo "=== NOTE === If you see a mismatch below, please update asan_win_dll_thunk.cc"
-// RUN: diff %t.dll_imports %t.exported_wrappers
+// RUN: diff %t.dll_imports-sorted %t.exported_wrappers-sorted
// REQUIRES: asan-static-runtime
#include <stdio.h>
diff --git a/test/asan/TestCases/Windows/dll_intercept_memchr.cc b/test/asan/TestCases/Windows/dll_intercept_memchr.cc
index 1435bdc50127e..4f794a212706a 100644
--- a/test/asan/TestCases/Windows/dll_intercept_memchr.cc
+++ b/test/asan/TestCases/Windows/dll_intercept_memchr.cc
@@ -2,6 +2,12 @@
// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+// On windows 64-bit, the memchr function is written in assembly and is not
+// hookable with the interception library. There is not enough padding before
+// the function and there is a short jump on the second instruction which
+// doesn't not allow enough space to encode a 64-bit indirect jump.
+// UNSUPPORTED: x86_64-windows
+
#include <string.h>
extern "C" __declspec(dllexport)
diff --git a/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc b/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc
index c5f44df3faaf5..4e28905923cc2 100644
--- a/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc
+++ b/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc
@@ -24,7 +24,7 @@ int test_function() {
call_memcpy(&memcpy, buff2, buff1, 6);
// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
// CHECK: WRITE of size 6 at [[ADDR]] thread T0
-// CHECK-NEXT: __asan_{{.*}}memcpy
+// CHECK-NEXT: __asan_{{.*}}mem{{.*}}
// CHECK-NEXT: call_memcpy
// CHECK-NEXT: test_function {{.*}}dll_intercept_memcpy_indirect.cc:[[@LINE-5]]
// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset {{.*}} in frame
diff --git a/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc b/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc
index 8306a737bfffa..b514c994c1dfe 100644
--- a/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc
+++ b/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc
@@ -10,7 +10,7 @@ struct C {
extern "C" __declspec(dllexport)
int test_function() {
C *buffer = new C[42];
- buffer[-2].x = 42;
+ buffer[-(1 + sizeof(void*) / 4)].x = 42;
// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
// CHECK: WRITE of size 4 at [[ADDR]] thread T0
// CHECK-NEXT: test_function {{.*}}dll_operator_array_new_with_dtor_left_oob.cc:[[@LINE-3]]
@@ -19,7 +19,7 @@ int test_function() {
// FIXME: Currently it says "4 bytes ... left of 172-byte region",
// should be "8 bytes ... left of 168-byte region", see
// https://code.google.com/p/address-sanitizer/issues/detail?id=314
-// CHECK: [[ADDR]] is located {{.*}} bytes to the left of 172-byte region
+// CHECK: [[ADDR]] is located {{.*}} bytes to the left of {{(172|176)}}-byte region
// FIXME: Should get rid of the malloc/free frames called from the inside of
// operator new/delete in DLLs when using -MT CRT.
// FIXME: The operator new frame should have [].
diff --git a/test/asan/TestCases/Windows/free_hook_realloc.cc b/test/asan/TestCases/Windows/free_hook_realloc.cc
index 297218bf8e99f..11e8c9975cf3b 100644
--- a/test/asan/TestCases/Windows/free_hook_realloc.cc
+++ b/test/asan/TestCases/Windows/free_hook_realloc.cc
@@ -5,6 +5,9 @@
// FIXME: merge this with the common free_hook_realloc test when we can run
// common tests on Windows.
+// FIXME: Doesn't work with DLLs
+// XFAIL: win32-dynamic-asan
+
#include <stdlib.h>
#include <io.h>
#include <sanitizer/allocator_interface.h>
diff --git a/test/asan/TestCases/Windows/global_dead_strip.c b/test/asan/TestCases/Windows/global_dead_strip.c
new file mode 100644
index 0000000000000..e68549050be6f
--- /dev/null
+++ b/test/asan/TestCases/Windows/global_dead_strip.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cl_asan /O0 %s /Fe%t.exe
+// RUN: %env_asan_opts=report_globals=2 %t.exe 2>&1 | FileCheck %s --check-prefix=NOSTRIP
+// RUN: %clang_cl_asan /O2 %s /Fe%t.exe -link -opt:ref
+// RUN: %env_asan_opts=report_globals=2 %t.exe 2>&1 | FileCheck %s --check-prefix=STRIP
+
+#include <stdio.h>
+int dead_global = 42;
+int live_global = 0;
+int main() {
+ puts("main");
+ return live_global;
+}
+
+// Check that our global registration scheme works with MSVC's linker dead
+// stripping (/OPT:REF).
+
+// NOSTRIP: Added Global{{.*}}name=dead_global
+// NOSTRIP: Added Global{{.*}}name=live_global
+// NOSTRIP: main
+
+// STRIP-NOT: Added Global{{.*}}name=dead_global
+// STRIP: Added Global{{.*}}name=live_global
+// STRIP: main
diff --git a/test/asan/TestCases/Windows/intercept_memcpy.cc b/test/asan/TestCases/Windows/intercept_memcpy.cc
index 9ee984b1873db..6e45e7fc6b309 100644
--- a/test/asan/TestCases/Windows/intercept_memcpy.cc
+++ b/test/asan/TestCases/Windows/intercept_memcpy.cc
@@ -22,8 +22,8 @@ int main() {
call_memcpy(&memcpy, buff2, buff1, 6);
// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
// CHECK: WRITE of size 6 at [[ADDR]] thread T0
-// CHECK-NEXT: __asan_{{.*}}memcpy
-// CHECK-NEXT: call_memcpy
+// CHECK-NEXT: __asan_{{.*}}mem{{.*}}
+// CHECK-NEXT: call_mem{{.*}}
// CHECK-NEXT: main {{.*}}intercept_memcpy.cc:[[@LINE-5]]
// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset {{.*}} in frame
// CHECK-NEXT: #0 {{.*}} main
diff --git a/test/asan/TestCases/Windows/on_error_callback.cc b/test/asan/TestCases/Windows/on_error_callback.cc
deleted file mode 100644
index 9e690a342b564..0000000000000
--- a/test/asan/TestCases/Windows/on_error_callback.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s
-
-// FIXME: merge this with the common on_error_callback test when we can run
-// common tests on Windows.
-
-#include <stdio.h>
-#include <stdlib.h>
-
-extern "C"
-void __asan_on_error() {
- fprintf(stderr, "__asan_on_error called");
- fflush(0);
-}
-
-int main() {
- char *x = (char*)malloc(10 * sizeof(char));
- free(x);
- return x[5];
- // CHECK: __asan_on_error called
-}
diff --git a/test/asan/TestCases/Windows/oom.cc b/test/asan/TestCases/Windows/oom.cc
index 3475af79e6a4c..59cc7ed0e9d12 100644
--- a/test/asan/TestCases/Windows/oom.cc
+++ b/test/asan/TestCases/Windows/oom.cc
@@ -1,5 +1,6 @@
// RUN: %clang_cl_asan -O0 %s -Fe%t
// RUN: not %run %t 2>&1 | FileCheck %s
+// REQUIRES: asan-32-bits
#include <malloc.h>
diff --git a/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc b/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc
index 63f2929bd89be..aae9d5ec82be2 100644
--- a/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc
+++ b/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc
@@ -8,7 +8,7 @@ struct C {
int main() {
C *buffer = new C[42];
- buffer[-2].x = 42;
+ buffer[-(1 + sizeof(void*) / 4)].x = 42;
// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
// CHECK: WRITE of size 4 at [[ADDR]] thread T0
// CHECK-NEXT: {{#0 .* main .*operator_array_new_with_dtor_left_oob.cc}}:[[@LINE-3]]
@@ -16,7 +16,7 @@ int main() {
// FIXME: Currently it says "4 bytes ... left of 172-byte region",
// should be "8 bytes ... left of 168-byte region", see
// https://code.google.com/p/address-sanitizer/issues/detail?id=314
-// CHECK: [[ADDR]] is located {{.*}} bytes to the left of 172-byte region
+// CHECK: [[ADDR]] is located {{.*}} bytes to the left of {{(172|176)}}-byte region
// CHECK-LABEL: allocated by thread T0 here:
// FIXME: The 'operator new' frame should have [].
// CHECK-NEXT: {{#0 .* operator new}}
diff --git a/test/asan/TestCases/Windows/queue_user_work_item.cc b/test/asan/TestCases/Windows/queue_user_work_item.cc
index 2a0b622f62185..2a8beb828ee29 100644
--- a/test/asan/TestCases/Windows/queue_user_work_item.cc
+++ b/test/asan/TestCases/Windows/queue_user_work_item.cc
@@ -1,11 +1,6 @@
// Make sure we can throw exceptions from work items executed via
// QueueUserWorkItem.
//
-// Clang doesn't support exceptions on Windows yet, so for the time being we
-// build this program in two parts: the code with exceptions is built with CL,
-// the rest is built with Clang. This represents the typical scenario when we
-// build a large project using "clang-cl -fallback -fsanitize=address".
-//
// RUN: %clangxx_asan %s -o %t.exe
// RUN: %run %t.exe 2>&1 | FileCheck %s
diff --git a/test/asan/TestCases/Windows/queue_user_work_item_report.cc b/test/asan/TestCases/Windows/queue_user_work_item_report.cc
index e500a919fdaed..26bd5e09d3ebd 100644
--- a/test/asan/TestCases/Windows/queue_user_work_item_report.cc
+++ b/test/asan/TestCases/Windows/queue_user_work_item_report.cc
@@ -12,8 +12,6 @@ DWORD CALLBACK work_item(LPVOID) {
// CHECK: AddressSanitizer: stack-buffer-underflow on address [[ADDR:0x[0-9a-f]+]]
// CHECK: WRITE of size 1 at [[ADDR]] thread T1
// CHECK: {{#0 .* work_item.*queue_user_work_item_report.cc}}:[[@LINE-3]]
-// CHECK: Address [[ADDR]] is located in stack of thread T1 at offset {{.*}} in frame
-// CHECK: work_item
SetEvent(done);
return 0;
}
diff --git a/test/asan/TestCases/Windows/report_after_syminitialize.cc b/test/asan/TestCases/Windows/report_after_syminitialize.cc
index 20bf695141798..eec50297478c0 100644
--- a/test/asan/TestCases/Windows/report_after_syminitialize.cc
+++ b/test/asan/TestCases/Windows/report_after_syminitialize.cc
@@ -4,6 +4,8 @@
#include <windows.h>
#include <dbghelp.h>
+#pragma comment(lib, "dbghelp")
+
int main() {
// Make sure the RTL recovers from "no options enabled" dbghelp setup.
SymSetOptions(0);
@@ -16,8 +18,8 @@ int main() {
// CHECK: ERROR: AddressSanitizer: access-violation on unknown address
// CHECK: The signal is caused by a WRITE memory access.
// CHECK: Hint: address points to the zero page.
- // CHECK-NEXT: {{WARNING: Failed to use and restart external symbolizer}}
- // CHECK-NEXT: {{WARNING: .*DbgHelp}}
+ // CHECK: {{WARNING: .*DbgHelp}}
+ // CHECK: {{WARNING: Failed to use and restart external symbolizer}}
// CHECK: {{#0 0x.* in main.*report_after_syminitialize.cc:}}[[@LINE-6]]
// CHECK: AddressSanitizer can not provide additional info.
}
diff --git a/test/asan/TestCases/Windows/shadow_conflict_32.cc b/test/asan/TestCases/Windows/shadow_conflict_32.cc
new file mode 100644
index 0000000000000..7c6d94b37483c
--- /dev/null
+++ b/test/asan/TestCases/Windows/shadow_conflict_32.cc
@@ -0,0 +1,29 @@
+// Load this DLL at the default 32-bit ASan shadow base, and test how we dump
+// the process memory layout.
+// REQUIRES: asan-32-bits
+//
+// RUN: %clang_cl_asan -DBUILD_DLL -LD %s -Fe%t_dll.dll -link -base:0x30000000 -fixed -dynamicbase:no
+// RUN: %clang_cl_asan %s -Fe%t.exe -link %t_dll.lib
+// RUN: not %run %t.exe 2>&1 | FileCheck %s
+
+#ifndef BUILD_DLL
+#include <stdio.h>
+
+extern "C" __declspec(dllimport) int test_function();
+
+int main() {
+ fprintf(stderr, "should have failed to initialize, DLL got loaded near 0x%p\n",
+ (void *)&test_function);
+}
+
+#else
+extern "C" __declspec(dllexport) int test_function() { return 0; }
+#endif
+
+// CHECK: =={{[0-9]+}}==Shadow memory range interleaves with an existing memory mapping. ASan cannot proceed correctly. ABORTING.
+// CHECK: =={{[0-9]+}}==ASan shadow was supposed to be located in the [0x2fff0000-0x3fffffff] range.
+// CHECK: =={{[0-9]+}}==Dumping process modules
+
+// CHECK-DAG: {{0x30000000-0x300.....}} {{.*}}\shadow_conflict_32.cc.tmp_dll.dll
+// CHECK-DAG: {{0x........-0x........}} {{.*}}\shadow_conflict_32.cc.tmp.exe
+// CHECK-DAG: {{0x........-0x........}} {{.*}}\ntdll.dll
diff --git a/test/asan/TestCases/Windows/shadow_mapping_failure.cc b/test/asan/TestCases/Windows/shadow_mapping_failure.cc
index 9b83947442ed0..510f169401dc3 100644
--- a/test/asan/TestCases/Windows/shadow_mapping_failure.cc
+++ b/test/asan/TestCases/Windows/shadow_mapping_failure.cc
@@ -1,5 +1,6 @@
// RUN: %clang_cl_asan -O0 %s -Fe%t
// RUN: not %run %t 2>&1 | FileCheck %s
+// REQUIRES: asan-32-bits
#include <stdio.h>
diff --git a/test/asan/TestCases/Windows/tls_init.cc b/test/asan/TestCases/Windows/tls_init.cc
new file mode 100644
index 0000000000000..c29c4a377834b
--- /dev/null
+++ b/test/asan/TestCases/Windows/tls_init.cc
@@ -0,0 +1,51 @@
+// RUN: %clang_cl_asan %s -Fe%t.exe
+// RUN: %run %t.exe | FileCheck %s
+
+// CHECK: my_thread_callback
+// CHECK: ran_before_main: 1
+
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+
+#pragma comment (lib, "dbghelp")
+
+static bool ran_before_main = false;
+
+extern "C" void __asan_init(void);
+
+static void NTAPI /*__attribute__((no_sanitize_address))*/
+my_thread_callback(PVOID module, DWORD reason, PVOID reserved) {
+ ran_before_main = true;
+ static const char str[] = "my_thread_callback\n";
+
+ // Fail the test if we aren't called for the expected reason or we can't write
+ // stdout.
+ if (reason != DLL_PROCESS_ATTACH)
+ return;
+ HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (!out || out == INVALID_HANDLE_VALUE)
+ return;
+
+ DWORD written = 0;
+ WriteFile(out, &str[0], sizeof(str), &written, NULL);
+}
+
+extern "C" {
+#pragma const_seg(".CRT$XLC")
+extern const PIMAGE_TLS_CALLBACK p_thread_callback;
+const PIMAGE_TLS_CALLBACK p_thread_callback = my_thread_callback;
+#pragma const_seg()
+}
+
+#ifdef _WIN64
+#pragma comment(linker, "/INCLUDE:_tls_used")
+#pragma comment(linker, "/INCLUDE:p_thread_callback")
+#else
+#pragma comment(linker, "/INCLUDE:__tls_used")
+#pragma comment(linker, "/INCLUDE:_p_thread_callback")
+#endif
+
+int main() {
+ printf("ran_before_main: %d\n", ran_before_main);
+}
diff --git a/test/asan/TestCases/Windows/unsymbolized.cc b/test/asan/TestCases/Windows/unsymbolized.cc
index e44b4bbabb87f..5854dc56d2e99 100644
--- a/test/asan/TestCases/Windows/unsymbolized.cc
+++ b/test/asan/TestCases/Windows/unsymbolized.cc
@@ -20,6 +20,6 @@ int do_uaf(void) {
free(x);
return x[5];
// CHECK: AddressSanitizer: heap-use-after-free
- // CHECK: #0 {{0x[a-f0-9]+ \(.*[\\/]unsymbolized.cc.*.exe\+0x40[a-f0-9]{4}\)}}
- // CHECK: #1 {{0x[a-f0-9]+ \(.*[\\/]unsymbolized.cc.*.exe\+0x40[a-f0-9]{4}\)}}
+ // CHECK: #0 {{0x[a-f0-9]+ \(.*[\\/]unsymbolized.cc.*.exe\+(0x40|0x14000)[a-f0-9]{4}\)}}
+ // CHECK: #1 {{0x[a-f0-9]+ \(.*[\\/]unsymbolized.cc.*.exe\+(0x40|0x14000)[a-f0-9]{4}\)}}
}
diff --git a/test/asan/TestCases/alloca_big_alignment.cc b/test/asan/TestCases/alloca_big_alignment.cc
index 2ede3f949b24a..0b49424bfae5d 100644
--- a/test/asan/TestCases/alloca_big_alignment.cc
+++ b/test/asan/TestCases/alloca_big_alignment.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
+// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
//
diff --git a/test/asan/TestCases/alloca_detect_custom_size_.cc b/test/asan/TestCases/alloca_detect_custom_size_.cc
index 2b0f573de3d05..271359bf70973 100644
--- a/test/asan/TestCases/alloca_detect_custom_size_.cc
+++ b/test/asan/TestCases/alloca_detect_custom_size_.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
+// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
//
diff --git a/test/asan/TestCases/alloca_instruments_all_paddings.cc b/test/asan/TestCases/alloca_instruments_all_paddings.cc
index e2c7fafb193ed..5bf6f80ac4ce7 100644
--- a/test/asan/TestCases/alloca_instruments_all_paddings.cc
+++ b/test/asan/TestCases/alloca_instruments_all_paddings.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
-// RUN: %clangxx_asan -O3 -mllvm -asan-instrument-allocas %s -o %t
+// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t
+// RUN: %clangxx_asan -O3 -mllvm -asan-instrument-dynamic-allocas %s -o %t
// RUN: %run %t 2>&1
//
diff --git a/test/asan/TestCases/alloca_loop_unpoisoning.cc b/test/asan/TestCases/alloca_loop_unpoisoning.cc
index 5392792926748..1efada10979ae 100644
--- a/test/asan/TestCases/alloca_loop_unpoisoning.cc
+++ b/test/asan/TestCases/alloca_loop_unpoisoning.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
+// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t
// RUN: %run %t 2>&1
//
// REQUIRES: stable-runtime
diff --git a/test/asan/TestCases/alloca_overflow_partial.cc b/test/asan/TestCases/alloca_overflow_partial.cc
index 590f35465dadb..afac40ce6b9a7 100644
--- a/test/asan/TestCases/alloca_overflow_partial.cc
+++ b/test/asan/TestCases/alloca_overflow_partial.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
+// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
//
diff --git a/test/asan/TestCases/alloca_overflow_right.cc b/test/asan/TestCases/alloca_overflow_right.cc
index caec846838eff..615dd1485be1b 100644
--- a/test/asan/TestCases/alloca_overflow_right.cc
+++ b/test/asan/TestCases/alloca_overflow_right.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
+// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
//
diff --git a/test/asan/TestCases/alloca_safe_access.cc b/test/asan/TestCases/alloca_safe_access.cc
index 240454fd55e42..1cd0dada7b45c 100644
--- a/test/asan/TestCases/alloca_safe_access.cc
+++ b/test/asan/TestCases/alloca_safe_access.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
+// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t
// RUN: %run %t 2>&1
//
diff --git a/test/asan/TestCases/alloca_underflow_left.cc b/test/asan/TestCases/alloca_underflow_left.cc
index 6e7061f7cfe24..8720e8cce24b3 100644
--- a/test/asan/TestCases/alloca_underflow_left.cc
+++ b/test/asan/TestCases/alloca_underflow_left.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
+// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
//
diff --git a/test/asan/TestCases/alloca_vla_interact.cc b/test/asan/TestCases/alloca_vla_interact.cc
index 3873c3fceea85..4717c9d977ed5 100644
--- a/test/asan/TestCases/alloca_vla_interact.cc
+++ b/test/asan/TestCases/alloca_vla_interact.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
+// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t
// RUN: %run %t 2>&1
//
// REQUIRES: stable-runtime
diff --git a/test/asan/TestCases/atexit_stats.cc b/test/asan/TestCases/atexit_stats.cc
index 42a3fbf23f556..f0b5830b405aa 100644
--- a/test/asan/TestCases/atexit_stats.cc
+++ b/test/asan/TestCases/atexit_stats.cc
@@ -2,9 +2,9 @@
// RUN: %clangxx_asan -O3 %s -o %t
// RUN: %env_asan_opts=atexit=1:print_stats=1 %run %t 2>&1 | FileCheck %s
//
-// No atexit output on Android due to
+// No atexit output in older versions of Android due to
// https://code.google.com/p/address-sanitizer/issues/detail?id=263
-// XFAIL: android
+// UNSUPPORTED: android
#include <stdlib.h>
#if !defined(__APPLE__) && !defined(__FreeBSD__)
diff --git a/test/asan/TestCases/coverage-order-pcs.cc b/test/asan/TestCases/coverage-order-pcs.cc
index dcab69474a6c3..e81c910454556 100644
--- a/test/asan/TestCases/coverage-order-pcs.cc
+++ b/test/asan/TestCases/coverage-order-pcs.cc
@@ -19,7 +19,7 @@
//
// RUN: rm -rf $DIR
// Ordering works only in 64-bit mode for now.
-// REQUIRES: asan-64-bits
+// REQUIRES: asan-64-bits, shell
// UNSUPPORTED: android
#include <stdio.h>
diff --git a/test/asan/TestCases/coverage-pc-buffer.cc b/test/asan/TestCases/coverage-pc-buffer.cc
deleted file mode 100644
index 5895a5c45d153..0000000000000
--- a/test/asan/TestCases/coverage-pc-buffer.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Test __sanitizer_coverage_pc_buffer().
-
-// RUN: %clangxx_asan -fsanitize-coverage=edge %s -o %t && %run %t
-
-// UNSUPPORTED: android
-
-#include <assert.h>
-#include <sanitizer/coverage_interface.h>
-#include <stdio.h>
-
-static volatile int sink;
-__attribute__((noinline)) void bar() { sink = 2; }
-__attribute__((noinline)) void foo() { sink = 1; }
-
-void assertNotZeroPcs(uintptr_t *buf, uintptr_t size) {
- assert(buf);
- for (uintptr_t i = 0; i < size; ++i)
- assert(buf[i]);
-}
-
-int main() {
- {
- uintptr_t *buf = NULL;
- uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf);
- assertNotZeroPcs(buf, sz);
- assert(sz);
- }
-
- {
- uintptr_t *buf = NULL;
- uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf);
- // call functions for the first time.
- foo();
- bar();
- uintptr_t *buf1 = NULL;
- uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer(&buf1);
- assertNotZeroPcs(buf1, sz1);
- assert(buf1 == buf);
- assert(sz1 > sz);
- }
-
- {
- uintptr_t *buf = NULL;
- uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf);
- // second call shouldn't increase coverage.
- bar();
- uintptr_t *buf1 = NULL;
- uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer(&buf1);
- assertNotZeroPcs(buf1, sz1);
- assert(buf1 == buf);
- assert(sz1 == sz);
- }
-
- {
- uintptr_t *buf = NULL;
- uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf);
- // reset coverage to 0.
- __sanitizer_reset_coverage();
- uintptr_t *buf1 = NULL;
- uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer(&buf1);
- assertNotZeroPcs(buf1, sz1);
- assert(buf1 == buf);
- assert(sz1 < sz);
- }
-}
diff --git a/test/asan/TestCases/coverage-tracing.cc b/test/asan/TestCases/coverage-tracing.cc
index b7755f847dbb6..278cfb141f07d 100644
--- a/test/asan/TestCases/coverage-tracing.cc
+++ b/test/asan/TestCases/coverage-tracing.cc
@@ -24,7 +24,7 @@
// RUN: not diff b.points bf.points
// RUN: rm -rf %T/coverage-tracing
//
-// REQUIRES: asan-64-bits
+// REQUIRES: asan-64-bits, shell
// UNSUPPORTED: android
#include <stdlib.h>
diff --git a/test/asan/TestCases/debug_double_free.cc b/test/asan/TestCases/debug_double_free.cc
new file mode 100644
index 0000000000000..c3699b9762d82
--- /dev/null
+++ b/test/asan/TestCases/debug_double_free.cc
@@ -0,0 +1,50 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+#include <sanitizer/asan_interface.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+// FIXME: Doesn't work with DLLs
+// XFAIL: win32-dynamic-asan
+
+// If we use %p with MSVC, it comes out all upper case. Use %08x to get
+// lowercase hex.
+#ifdef _MSC_VER
+# ifdef _WIN64
+# define PTR_FMT "0x%08llx"
+# else
+# define PTR_FMT "0x%08x"
+# endif
+#else
+# define PTR_FMT "%p"
+#endif
+
+char *heap_ptr;
+
+int main() {
+ // Disable stderr buffering. Needed on Windows.
+ setvbuf(stderr, NULL, _IONBF, 0);
+
+ heap_ptr = (char *)malloc(10);
+ fprintf(stderr, "heap_ptr: " PTR_FMT "\n", heap_ptr);
+ // CHECK: heap_ptr: 0x[[ADDR:[0-9a-f]+]]
+
+ free(heap_ptr);
+ free(heap_ptr); // BOOM
+ return 0;
+}
+
+void __asan_on_error() {
+ int present = __asan_report_present();
+ void *addr = __asan_get_report_address();
+ const char *description = __asan_get_report_description();
+
+ fprintf(stderr, "%s\n", (present == 1) ? "report present" : "");
+ // CHECK: report present
+ fprintf(stderr, "addr: " PTR_FMT "\n", addr);
+ // CHECK: addr: {{0x0*}}[[ADDR]]
+ fprintf(stderr, "description: %s\n", description);
+ // CHECK: description: double-free
+}
+
+// CHECK: AddressSanitizer: attempting double-free on {{0x0*}}[[ADDR]] in thread T0
diff --git a/test/asan/TestCases/debug_mapping.cc b/test/asan/TestCases/debug_mapping.cc
index bd05f6aab3533..40083f02853fc 100644
--- a/test/asan/TestCases/debug_mapping.cc
+++ b/test/asan/TestCases/debug_mapping.cc
@@ -6,6 +6,12 @@
#include <stdio.h>
#include <stdlib.h>
+#if _WIN64
+#define PTR "%llx"
+#else
+#define PTR "%lx"
+#endif
+
// printed because of verbosity=1
// CHECK: SHADOW_SCALE: [[SCALE:[0-9]+]]
// CHECK: SHADOW_OFFSET: [[OFFSET:0x[0-9a-f]+]]
@@ -15,7 +21,7 @@ int main() {
__asan_get_shadow_mapping(&scale, &offset);
fprintf(stderr, "scale: %d\n", (int)scale);
- fprintf(stderr, "offset: 0x%lx\n", offset);
+ fprintf(stderr, "offset: 0x" PTR "\n", (void*)offset);
// CHECK: scale: [[SCALE]]
// CHECK: offset: [[OFFSET]]
diff --git a/test/asan/TestCases/debug_report.cc b/test/asan/TestCases/debug_report.cc
index 124ae5d76642d..34bc06eba62c1 100644
--- a/test/asan/TestCases/debug_report.cc
+++ b/test/asan/TestCases/debug_report.cc
@@ -6,6 +6,9 @@
#include <stdio.h>
#include <stdlib.h>
+// FIXME: Doesn't work with DLLs
+// XFAIL: win32-dynamic-asan
+
int main() {
// Disable stderr buffering. Needed on Windows.
setvbuf(stderr, NULL, _IONBF, 0);
diff --git a/test/asan/TestCases/debug_stacks.cc b/test/asan/TestCases/debug_stacks.cc
index 857e905094bee..7c320bfcb2d98 100644
--- a/test/asan/TestCases/debug_stacks.cc
+++ b/test/asan/TestCases/debug_stacks.cc
@@ -5,6 +5,12 @@
// FIXME: Figure out why allocation/free stack traces may be too short on ARM.
// REQUIRES: stable-runtime
+#if _WIN64
+#define PTR "%llx"
+#else
+#define PTR "%lx"
+#endif
+
#include <sanitizer/asan_interface.h>
#include <stdio.h>
#include <stdlib.h>
@@ -35,9 +41,9 @@ int main() {
// CHECK: alloc stack retval ok
fprintf(stderr, "thread id = %d\n", thread_id);
// CHECK: thread id = 0
- fprintf(stderr, "0x%lx\n", trace[0]);
+ fprintf(stderr, "0x" PTR "\n", trace[0]);
// CHECK: [[ALLOC_FRAME_0:0x[0-9a-f]+]]
- fprintf(stderr, "0x%lx\n", trace[1]);
+ fprintf(stderr, "0x" PTR "\n", trace[1]);
// CHECK: [[ALLOC_FRAME_1:0x[0-9a-f]+]]
num_frames = 100;
@@ -48,9 +54,9 @@ int main() {
// CHECK: free stack retval ok
fprintf(stderr, "thread id = %d\n", thread_id);
// CHECK: thread id = 0
- fprintf(stderr, "0x%lx\n", trace[0]);
+ fprintf(stderr, "0x" PTR "\n", trace[0]);
// CHECK: [[FREE_FRAME_0:0x[0-9a-f]+]]
- fprintf(stderr, "0x%lx\n", trace[1]);
+ fprintf(stderr, "0x" PTR "\n", trace[1]);
// CHECK: [[FREE_FRAME_1:0x[0-9a-f]+]]
mem[0] = 'A'; // BOOM
diff --git a/test/asan/TestCases/deep_stack_uaf.cc b/test/asan/TestCases/deep_stack_uaf.cc
index 95032f2bd4f55..bdf0dbdb4a4bd 100644
--- a/test/asan/TestCases/deep_stack_uaf.cc
+++ b/test/asan/TestCases/deep_stack_uaf.cc
@@ -2,8 +2,7 @@
// RUN: %clangxx_asan -O0 %s -o %t 2>&1
// RUN: %env_asan_opts=malloc_context_size=120:redzone=512 not %run %t 2>&1 | FileCheck %s
-// XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
+// REQUIRES: stable-runtime
#include <stdlib.h>
#include <stdio.h>
diff --git a/test/asan/TestCases/default_options.cc b/test/asan/TestCases/default_options.cc
index a3aa6637e8acd..27af76d7fe38a 100644
--- a/test/asan/TestCases/default_options.cc
+++ b/test/asan/TestCases/default_options.cc
@@ -1,6 +1,9 @@
// RUN: %clangxx_asan -O2 %s -o %t
// RUN: %run %t 2>&1 | FileCheck %s
+// FIXME: Doesn't work with DLLs
+// XFAIL: win32-dynamic-asan
+
const char *kAsanDefaultOptions="verbosity=1 help=1";
extern "C"
diff --git a/test/asan/TestCases/double-free.cc b/test/asan/TestCases/double-free.cc
index 9bd418fc6c809..2a26b23fb1f10 100644
--- a/test/asan/TestCases/double-free.cc
+++ b/test/asan/TestCases/double-free.cc
@@ -7,9 +7,7 @@
// RUN: %clangxx_asan -O0 -fsanitize-recover=address %s -o %t 2>&1
// RUN: %env_asan_opts=halt_on_error=false %run %t 2>&1 | FileCheck %s --check-prefix CHECK-RECOVER
-
-// XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
+// REQUIRES: stable-runtime
#include <stdlib.h>
#include <string.h>
diff --git a/test/asan/TestCases/exitcode.cc b/test/asan/TestCases/exitcode.cc
new file mode 100644
index 0000000000000..cb10540999b7d
--- /dev/null
+++ b/test/asan/TestCases/exitcode.cc
@@ -0,0 +1,130 @@
+// RUN: %clangxx_asan -g %stdcxx11 -Wno-deprecated-declarations %s -o %t
+// RUN: %env_asan_opts=exitcode=42 %run %t | FileCheck %s
+
+// Android doesn't have spawn.h or posix_spawn.
+// UNSUPPORTED: android
+
+// CHECK: got expected 42 exit code
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef _WIN32
+#include <windows.h>
+
+int spawn_child(char **argv) {
+ // Set an environment variable to tell the child process to interrupt
+ // itself.
+ if (!SetEnvironmentVariableW(L"CRASH_FOR_TEST", L"1")) {
+ printf("SetEnvironmentVariableW failed (0x%8lx).\n", GetLastError());
+ fflush(stdout);
+ exit(1);
+ }
+
+ STARTUPINFOW si;
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+
+ PROCESS_INFORMATION pi;
+ memset(&pi, 0, sizeof(pi));
+
+ if (!CreateProcessW(nullptr, // No module name (use command line)
+ GetCommandLineW(), // Command line
+ nullptr, // Process handle not inheritable
+ nullptr, // Thread handle not inheritable
+ TRUE, // Set handle inheritance to TRUE
+ 0, // No flags
+ nullptr, // Use parent's environment block
+ nullptr, // Use parent's starting directory
+ &si, &pi)) {
+ printf("CreateProcess failed (0x%08lx).\n", GetLastError());
+ fflush(stdout);
+ exit(1);
+ }
+
+ WaitForSingleObject(pi.hProcess, INFINITE);
+
+ DWORD exit_code;
+ if (!GetExitCodeProcess(pi.hProcess, &exit_code)) {
+ printf("GetExitCodeProcess failed (0x%08lx).\n", GetLastError());
+ fflush(stdout);
+ exit(1);
+ }
+
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+
+ return exit_code;
+}
+#else
+#include <spawn.h>
+#include <errno.h>
+#include <sys/wait.h>
+
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#endif
+
+#if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
+#define USE_NSGETENVIRON 1
+#else
+#define USE_NSGETENVIRON 0
+#endif
+
+#if !USE_NSGETENVIRON
+extern char **environ;
+#else
+#include <crt_externs.h> // _NSGetEnviron
+#endif
+
+int spawn_child(char **argv) {
+ setenv("CRASH_FOR_TEST", "1", 1);
+
+#if !USE_NSGETENVIRON
+ char **envp = environ;
+#else
+ char **envp = *_NSGetEnviron();
+#endif
+
+ pid_t pid;
+ int err = posix_spawn(&pid, argv[0], nullptr, nullptr, argv, envp);
+ if (err) {
+ printf("posix_spawn failed: %d\n", err);
+ fflush(stdout);
+ exit(1);
+ }
+
+ // Wait until the child exits.
+ int status;
+ pid_t wait_result_pid;
+ do {
+ wait_result_pid = waitpid(pid, &status, 0);
+ } while (wait_result_pid == -1 && errno == EINTR);
+
+ if (wait_result_pid != pid || !WIFEXITED(status)) {
+ printf("error in waitpid\n");
+ fflush(stdout);
+ exit(1);
+ }
+
+ // Return the exit status.
+ return WEXITSTATUS(status);
+}
+#endif
+
+int main(int argc, char **argv) {
+ int r = 0;
+ if (getenv("CRASH_FOR_TEST")) {
+ // Generate an asan report to test ASAN_OPTIONS=exitcode=42
+ int *p = new int;
+ delete p;
+ r = *p;
+ } else {
+ int exit_code = spawn_child(argv);
+ if (exit_code == 42) {
+ printf("got expected 42 exit code\n");
+ fflush(stdout);
+ }
+ }
+ return r;
+}
diff --git a/test/asan/TestCases/global-address.cpp b/test/asan/TestCases/global-address.cpp
new file mode 100644
index 0000000000000..0e56ca10c39c2
--- /dev/null
+++ b/test/asan/TestCases/global-address.cpp
@@ -0,0 +1,12 @@
+// RUN: %clangxx_asan -o %t %s
+// RUN: not %run %t 2>&1 | FileCheck %s
+#include <sanitizer/allocator_interface.h>
+
+int g_i = 42;
+int main() {
+ // CHECK: AddressSanitizer: attempting to call __sanitizer_get_allocated_size() for pointer which is not owned
+ // CHECK-NOT: ASAN:DEADLYSIGNAL
+ // CHECK: SUMMARY: AddressSanitizer: bad-__sanitizer_get_allocated_size
+ // CHECK-NOT: ASAN:DEADLYSIGNAL
+ return (int)__sanitizer_get_allocated_size(&g_i);
+}
diff --git a/test/asan/TestCases/ill.cc b/test/asan/TestCases/ill.cc
new file mode 100644
index 0000000000000..d7b5350916719
--- /dev/null
+++ b/test/asan/TestCases/ill.cc
@@ -0,0 +1,31 @@
+// Test the handle_sigill option.
+//
+// RUN: %clangxx_asan %s -o %t && %env_asan_opts=handle_sigill=0 not --crash %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
+// RUN: %clangxx_asan %s -o %t && %env_asan_opts=handle_sigill=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
+// REQUIRES: x86-target-arch
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+int main(int argc, char **argv) {
+#ifdef _WIN32
+ // Sometimes on Windows this test generates a WER fault dialog. Suppress that.
+ UINT new_flags = SEM_FAILCRITICALERRORS |
+ SEM_NOGPFAULTERRORBOX |
+ SEM_NOOPENFILEERRORBOX;
+ // Preserve existing error mode, as discussed at
+ // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx
+ UINT existing_flags = SetErrorMode(new_flags);
+ SetErrorMode(existing_flags | new_flags);
+#endif
+
+ if (argc)
+ __builtin_trap();
+ // Unreachable code to avoid confusing the Windows unwinder.
+#ifdef _WIN32
+ SetErrorMode(0);
+#endif
+}
+// CHECK0-NOT: ERROR: AddressSanitizer
+// CHECK1: ERROR: AddressSanitizer: {{ILL|illegal-instruction}} on unknown address {{0x0*}}
diff --git a/test/asan/TestCases/initialization-bug.cc b/test/asan/TestCases/initialization-bug.cc
index 6f361cb2bad86..b28174f59aeb2 100644
--- a/test/asan/TestCases/initialization-bug.cc
+++ b/test/asan/TestCases/initialization-bug.cc
@@ -1,12 +1,12 @@
// Test to make sure basic initialization order errors are caught.
-// RUN: %clangxx_asan -O0 %s %p/Helpers/initialization-bug-extra2.cc -o %t-INIT-ORDER-EXE
+// RUN: %clangxx_asan %macos_min_target_10_11 -O0 %s %p/Helpers/initialization-bug-extra2.cc -o %t-INIT-ORDER-EXE
// RUN: %env_asan_opts=check_initialization_order=true not %run %t-INIT-ORDER-EXE 2>&1 | FileCheck %s
// Do not test with optimization -- the error may be optimized away.
// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=186
-// XFAIL: darwin,win32
+// XFAIL: win32
// The test is expected to fail on OS X Yosemite and older
// UNSUPPORTED: osx-no-ld64-live_support
diff --git a/test/asan/TestCases/interception_failure_test.cc b/test/asan/TestCases/interception_failure_test.cc
index 63d8746678363..d85500b50486b 100644
--- a/test/asan/TestCases/interception_failure_test.cc
+++ b/test/asan/TestCases/interception_failure_test.cc
@@ -5,13 +5,20 @@
// RUN: %clangxx_asan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O2 %s -o %t && %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O3 %s -o %t && %run %t 2>&1 | FileCheck %s
-// On Windows, defining strtoll results in linker errors.
-// XFAIL: freebsd,win32
+// XFAIL: freebsd
+
+// On Windows, defining strtoll in a static build results in linker errors, but
+// it works with the dynamic runtime.
+// XFAIL: win32-static-asan
+
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
extern "C" long strtol(const char *nptr, char **endptr, int base) {
fprintf(stderr, "my_strtol_interceptor\n");
+ if (endptr)
+ *endptr = (char*)nptr + strlen(nptr);
return 0;
}
diff --git a/test/asan/TestCases/intra-object-overflow.cc b/test/asan/TestCases/intra-object-overflow.cc
index e48a261f55cc3..4032cc1448582 100644
--- a/test/asan/TestCases/intra-object-overflow.cc
+++ b/test/asan/TestCases/intra-object-overflow.cc
@@ -4,6 +4,8 @@
//
// FIXME: fix 32-bits.
// REQUIRES: asan-64-bits
+// FIXME: Implement ASan intra-object padding in Clang's MS record layout
+// UNSUPPORTED: win32
#include <stdio.h>
#include <stdlib.h>
class Foo {
diff --git a/test/asan/TestCases/invalid-free.cc b/test/asan/TestCases/invalid-free.cc
index dd59f5af32f22..be45e438bd45a 100644
--- a/test/asan/TestCases/invalid-free.cc
+++ b/test/asan/TestCases/invalid-free.cc
@@ -4,8 +4,7 @@
// Also works if no malloc context is available.
// RUN: %env_asan_opts=malloc_context_size=0:fast_unwind_on_malloc=0 not %run %t 2>&1 | FileCheck %s
// RUN: %env_asan_opts=malloc_context_size=0:fast_unwind_on_malloc=1 not %run %t 2>&1 | FileCheck %s
-// XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
+// REQUIRES: stable-runtime
#include <stdlib.h>
#include <string.h>
diff --git a/test/asan/TestCases/large_func_test.cc b/test/asan/TestCases/large_func_test.cc
index 8d9afaeb4a75c..1f5f7ccd5a6dc 100644
--- a/test/asan/TestCases/large_func_test.cc
+++ b/test/asan/TestCases/large_func_test.cc
@@ -2,8 +2,7 @@
// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
-// XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
+// REQUIRES: stable-runtime
#include <stdlib.h>
__attribute__((noinline))
diff --git a/test/asan/TestCases/on_error_callback.cc b/test/asan/TestCases/on_error_callback.cc
index 88a4d2dca49fd..f37d1eb7f7f83 100644
--- a/test/asan/TestCases/on_error_callback.cc
+++ b/test/asan/TestCases/on_error_callback.cc
@@ -1,5 +1,8 @@
// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// FIXME: Doesn't work with DLLs
+// XFAIL: win32-dynamic-asan
+
#include <stdio.h>
#include <stdlib.h>
diff --git a/test/asan/TestCases/printf-m.c b/test/asan/TestCases/printf-m.c
new file mode 100644
index 0000000000000..9cd5ae1c288e7
--- /dev/null
+++ b/test/asan/TestCases/printf-m.c
@@ -0,0 +1,14 @@
+// RUN: %clang_asan -O2 %s -o %t && %run %t
+
+// FIXME: printf is not intercepted on Windows yet.
+// UNSUPPORTED: win32
+
+#include <stdio.h>
+
+int main() {
+ char s[5] = {'w', 'o', 'r', 'l', 'd'};
+ // Test that %m does not consume an argument. If it does, %s would apply to
+ // the 5-character buffer, resulting in a stack-buffer-overflow report.
+ printf("%m %s, %.5s\n", "hello", s);
+ return 0;
+}
diff --git a/test/asan/TestCases/sanity_check_pure_c.c b/test/asan/TestCases/sanity_check_pure_c.c
index c3a43c8cacb2e..9d74996e43c55 100644
--- a/test/asan/TestCases/sanity_check_pure_c.c
+++ b/test/asan/TestCases/sanity_check_pure_c.c
@@ -3,10 +3,9 @@
// RUN: not %run %t 2>&1 | FileCheck %s
// Sanity checking a test in pure C with -pie.
-// RUN: %clang_asan -O2 %s -pie -fPIE -o %t
+// RUN: %clang_asan -O2 %s %pie %fPIE -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
-// XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
+// REQUIRES: stable-runtime
#include <stdlib.h>
int main() {
diff --git a/test/asan/TestCases/Linux/scariness_score_test.cc b/test/asan/TestCases/scariness_score_test.cc
index 24854132f539e..dee7a13b7b3be 100644
--- a/test/asan/TestCases/Linux/scariness_score_test.cc
+++ b/test/asan/TestCases/scariness_score_test.cc
@@ -1,7 +1,9 @@
// Test how we produce the scariness score.
// RUN: %clangxx_asan -O0 %s -o %t
-// RUN: export %env_asan_opts=detect_stack_use_after_return=1:handle_abort=1:print_scariness=1
+// On OSX and Windows, alloc_dealloc_mismatch=1 isn't 100% reliable, so it's
+// off by default. It's safe for these tests, though, so we turn it on.
+// RUN: export %env_asan_opts=detect_stack_use_after_return=1:handle_abort=1:print_scariness=1:alloc_dealloc_mismatch=1
// Make sure the stack is limited (may not be the default under GNU make)
// RUN: ulimit -s 4096
// RUN: not %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK1
@@ -155,12 +157,12 @@ int main(int argc, char **argv) {
case 19: *zero_ptr = 0; break;
case 20: *wild_addr = 0; break;
case 21: zero = *wild_addr; break;
- case 22: abort(); break;
- case 23: ((void (*)(void))wild_addr)(); break;
- case 24: delete (new int[10]); break;
- case 25: free((char*)malloc(100) + 10); break;
- case 26: memcpy(arr, arr+10, 20); break;
- case 27: UseAfterPoison(); break;
+ case 22: ((void (*)(void))wild_addr)(); break;
+ case 23: delete (new int[10]); break;
+ case 24: free((char*)malloc(100) + 10); break;
+ case 25: memcpy(arr, arr+10, 20); break;
+ case 26: UseAfterPoison(); break;
+ case 27: abort();
// CHECK1: SCARINESS: 12 (1-byte-read-heap-buffer-overflow)
// CHECK2: SCARINESS: 17 (4-byte-read-heap-buffer-overflow)
// CHECK3: SCARINESS: 33 (2-byte-write-heap-buffer-overflow)
@@ -182,11 +184,11 @@ int main(int argc, char **argv) {
// CHECK19: SCARINESS: 10 (null-deref)
// CHECK20: SCARINESS: 30 (wild-addr-write)
// CHECK21: SCARINESS: 20 (wild-addr-read)
- // CHECK22: SCARINESS: 10 (signal)
- // CHECK23: SCARINESS: 60 (wild-jump)
- // CHECK24: SCARINESS: 10 (alloc-dealloc-mismatch)
- // CHECK25: SCARINESS: 40 (bad-free)
- // CHECK26: SCARINESS: 10 (memcpy-param-overlap)
- // CHECK27: SCARINESS: 27 (4-byte-read-use-after-poison)
+ // CHECK22: SCARINESS: 60 (wild-jump)
+ // CHECK23: SCARINESS: 10 (alloc-dealloc-mismatch)
+ // CHECK24: SCARINESS: 40 (bad-free)
+ // CHECK25: SCARINESS: 10 (memcpy-param-overlap)
+ // CHECK26: SCARINESS: 27 (4-byte-read-use-after-poison)
+ // CHECK27: SCARINESS: 10 (signal)
}
}
diff --git a/test/asan/TestCases/set_shadow_test.c b/test/asan/TestCases/set_shadow_test.c
new file mode 100644
index 0000000000000..daa79a66a389b
--- /dev/null
+++ b/test/asan/TestCases/set_shadow_test.c
@@ -0,0 +1,69 @@
+// RUN: %clang_asan -O0 %s -o %t
+// RUN: %run %t 0x00 2>&1 | FileCheck %s -check-prefix=X00
+// RUN: not %run %t 0xf1 2>&1 | FileCheck %s -check-prefix=XF1
+// RUN: not %run %t 0xf2 2>&1 | FileCheck %s -check-prefix=XF2
+// RUN: not %run %t 0xf3 2>&1 | FileCheck %s -check-prefix=XF3
+// RUN: not %run %t 0xf5 2>&1 | FileCheck %s -check-prefix=XF5
+// RUN: not %run %t 0xf8 2>&1 | FileCheck %s -check-prefix=XF8
+
+// XFAIL: win32
+
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void __asan_set_shadow_00(size_t addr, size_t size);
+void __asan_set_shadow_f1(size_t addr, size_t size);
+void __asan_set_shadow_f2(size_t addr, size_t size);
+void __asan_set_shadow_f3(size_t addr, size_t size);
+void __asan_set_shadow_f5(size_t addr, size_t size);
+void __asan_set_shadow_f8(size_t addr, size_t size);
+
+char a __attribute__((aligned(8)));
+
+void f(long arg) {
+ size_t shadow_offset;
+ size_t shadow_scale;
+ __asan_get_shadow_mapping(&shadow_scale, &shadow_offset);
+ size_t addr = (((size_t)&a) >> shadow_scale) + shadow_offset;
+
+ switch (arg) {
+ // X00-NOT: AddressSanitizer
+ // X00: PASS
+ case 0x00:
+ return __asan_set_shadow_00(addr, 1);
+ // XF1: AddressSanitizer: stack-buffer-underflow
+ // XF1: [f1]
+ case 0xf1:
+ return __asan_set_shadow_f1(addr, 1);
+ // XF2: AddressSanitizer: stack-buffer-overflow
+ // XF2: [f2]
+ case 0xf2:
+ return __asan_set_shadow_f2(addr, 1);
+ // XF3: AddressSanitizer: stack-buffer-overflow
+ // XF3: [f3]
+ case 0xf3:
+ return __asan_set_shadow_f3(addr, 1);
+ // XF5: AddressSanitizer: stack-use-after-return
+ // XF5: [f5]
+ case 0xf5:
+ return __asan_set_shadow_f5(addr, 1);
+ // XF8: AddressSanitizer: stack-use-after-scope
+ // XF8: [f8]
+ case 0xf8:
+ return __asan_set_shadow_f8(addr, 1);
+ }
+ assert(0);
+}
+
+int main(int argc, char **argv) {
+ assert(argc > 1);
+
+ long arg = strtol(argv[1], 0, 16);
+ f(arg);
+ a = 1;
+ printf("PASS\n");
+ return 0;
+}
diff --git a/test/asan/TestCases/speculative_load.cc b/test/asan/TestCases/speculative_load.cc
index 2409d7a5eee34..fdf70eb39767a 100644
--- a/test/asan/TestCases/speculative_load.cc
+++ b/test/asan/TestCases/speculative_load.cc
@@ -27,6 +27,10 @@ struct S {
__asan_poison_memory_region(_data._s._ch, 23);
}
+ ~S() {
+ __asan_unpoison_memory_region(_data._s._ch, 23);
+ }
+
bool is_long() const {
return _data._s._size & 1;
}
diff --git a/test/asan/TestCases/strdup_oob_test.cc b/test/asan/TestCases/strdup_oob_test.cc
index 492555ad10194..60c5ef12a4735 100644
--- a/test/asan/TestCases/strdup_oob_test.cc
+++ b/test/asan/TestCases/strdup_oob_test.cc
@@ -9,6 +9,10 @@
// Unwind problem on arm: "main" is missing from the allocation stack trace.
// UNSUPPORTED: armv7l-unknown-linux-gnueabihf
+// FIXME: We fail to intercept strdup with the dynamic WinASan RTL, so it's not
+// in the stack trace.
+// XFAIL: win32-dynamic-asan
+
#include <string.h>
char kString[] = "foo";
diff --git a/test/asan/TestCases/strncasecmp_strict.c b/test/asan/TestCases/strncasecmp_strict.c
new file mode 100644
index 0000000000000..aa658402b42b3
--- /dev/null
+++ b/test/asan/TestCases/strncasecmp_strict.c
@@ -0,0 +1,67 @@
+// Test strict_string_checks option in strncmp function
+// RUN: %clang_asan %s -o %t
+
+// RUN: %env_asan_opts=strict_string_checks=false %run %t a 2>&1
+// RUN: %env_asan_opts=strict_string_checks=true %run %t a 2>&1
+// RUN: not %run %t b 2>&1 | FileCheck %s
+// RUN: not %run %t c 2>&1 | FileCheck %s
+// RUN: not %run %t d 2>&1 | FileCheck %s
+// RUN: not %run %t e 2>&1 | FileCheck %s
+// RUN: not %run %t f 2>&1 | FileCheck %s
+// RUN: not %run %t g 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=strict_string_checks=false %run %t h 2>&1
+// RUN: %env_asan_opts=strict_string_checks=true not %run %t h 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=strict_string_checks=false %run %t i 2>&1
+// RUN: %env_asan_opts=strict_string_checks=true not %run %t i 2>&1 | FileCheck %s
+
+// XFAIL: win32
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+int main(int argc, char **argv) {
+ assert(argc >= 2);
+ const size_t size = 100;
+ char fill = 'o';
+ char s1[size];
+ char s2[size];
+ memset(s1, fill, size);
+ memset(s2, fill, size);
+
+ switch (argv[1][0]) {
+ case 'a':
+ s1[size - 1] = 'z';
+ s2[size - 1] = 'x';
+ for (int i = 0; i <= size; ++i)
+ assert((strncasecmp(s1, s2, i) == 0) == (i < size));
+ s1[size - 1] = '\0';
+ s2[size - 1] = '\0';
+ assert(strncasecmp(s1, s2, 2*size) == 0);
+ break;
+ case 'b':
+ return strncasecmp(s1-1, s2, 1);
+ case 'c':
+ return strncasecmp(s1, s2-1, 1);
+ case 'd':
+ return strncasecmp(s1+size, s2, 1);
+ case 'e':
+ return strncasecmp(s1, s2+size, 1);
+ case 'f':
+ return strncasecmp(s1+1, s2, size);
+ case 'g':
+ return strncasecmp(s1, s2+1, size);
+ case 'h':
+ s1[size - 1] = '\0';
+ assert(strncasecmp(s1, s2, 2*size) != 0);
+ break;
+ case 'i':
+ s2[size - 1] = '\0';
+ assert(strncasecmp(s1, s2, 2*size) != 0);
+ break;
+ // CHECK: {{.*}}ERROR: AddressSanitizer: stack-buffer-{{ov|und}}erflow on address
+ }
+ return 0;
+}
diff --git a/test/asan/TestCases/strncmp_strict.c b/test/asan/TestCases/strncmp_strict.c
new file mode 100644
index 0000000000000..5b5429064cedc
--- /dev/null
+++ b/test/asan/TestCases/strncmp_strict.c
@@ -0,0 +1,65 @@
+// Test strict_string_checks option in strncmp function
+// RUN: %clang_asan %s -o %t
+
+// RUN: %env_asan_opts=strict_string_checks=false %run %t a 2>&1
+// RUN: %env_asan_opts=strict_string_checks=true %run %t a 2>&1
+// RUN: not %run %t b 2>&1 | FileCheck %s
+// RUN: not %run %t c 2>&1 | FileCheck %s
+// RUN: not %run %t d 2>&1 | FileCheck %s
+// RUN: not %run %t e 2>&1 | FileCheck %s
+// RUN: not %run %t f 2>&1 | FileCheck %s
+// RUN: not %run %t g 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=strict_string_checks=false %run %t h 2>&1
+// RUN: %env_asan_opts=strict_string_checks=true not %run %t h 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=strict_string_checks=false %run %t i 2>&1
+// RUN: %env_asan_opts=strict_string_checks=true not %run %t i 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+int main(int argc, char **argv) {
+ assert(argc >= 2);
+ const size_t size = 100;
+ char fill = 'o';
+ char s1[size];
+ char s2[size];
+ memset(s1, fill, size);
+ memset(s2, fill, size);
+
+ switch (argv[1][0]) {
+ case 'a':
+ s1[size - 1] = 'z';
+ s2[size - 1] = 'x';
+ for (int i = 0; i <= size; ++i)
+ assert((strncmp(s1, s2, i) == 0) == (i < size));
+ s1[size - 1] = '\0';
+ s2[size - 1] = '\0';
+ assert(strncmp(s1, s2, 2*size) == 0);
+ break;
+ case 'b':
+ return strncmp(s1-1, s2, 1);
+ case 'c':
+ return strncmp(s1, s2-1, 1);
+ case 'd':
+ return strncmp(s1+size, s2, 1);
+ case 'e':
+ return strncmp(s1, s2+size, 1);
+ case 'f':
+ return strncmp(s1+1, s2, size);
+ case 'g':
+ return strncmp(s1, s2+1, size);
+ case 'h':
+ s1[size - 1] = '\0';
+ assert(strncmp(s1, s2, 2*size) != 0);
+ break;
+ case 'i':
+ s2[size - 1] = '\0';
+ assert(strncmp(s1, s2, 2*size) != 0);
+ break;
+ // CHECK: {{.*}}ERROR: AddressSanitizer: stack-buffer-{{ov|und}}erflow on address
+ }
+ return 0;
+}
diff --git a/test/asan/TestCases/strncpy-overflow.cc b/test/asan/TestCases/strncpy-overflow.cc
index 651ae22795f15..7da9a8ff8eac5 100644
--- a/test/asan/TestCases/strncpy-overflow.cc
+++ b/test/asan/TestCases/strncpy-overflow.cc
@@ -4,8 +4,7 @@
// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
// REQUIRES: compiler-rt-optimized
-// XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
+// REQUIRES: stable-runtime
#include <string.h>
#include <stdlib.h>
diff --git a/test/asan/TestCases/strstr-1.c b/test/asan/TestCases/strstr-1.c
index d0fa25bc62ba3..06a8a8a55d999 100644
--- a/test/asan/TestCases/strstr-1.c
+++ b/test/asan/TestCases/strstr-1.c
@@ -15,7 +15,7 @@ int main(int argc, char **argv) {
char s1[4] = "acb";
__asan_poison_memory_region ((char *)&s1[2], 2);
r = strstr(s1, s2);
- // CHECK:'s1' <== Memory access at offset {{[0-9]+}} partially overflows this variable
+ // CHECK:'s1' <== Memory access at offset {{[0-9]+}} {{partially overflows this variable|is inside this variable}}
assert(r == s1 + 1);
return 0;
}
diff --git a/test/asan/TestCases/strstr_strict.c b/test/asan/TestCases/strstr_strict.c
index 35ad93c645ded..63e6b25a017c8 100644
--- a/test/asan/TestCases/strstr_strict.c
+++ b/test/asan/TestCases/strstr_strict.c
@@ -17,7 +17,7 @@ int main(int argc, char **argv) {
s2[size - 1]='\0';
char* r = strstr(s1, s2);
// CHECK: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}}
- // CHECK: READ of size 101
+ // CHECK: READ of size {{101|100}}
assert(r == s1);
free(s1);
free(s2);
diff --git a/test/asan/TestCases/suppressions-library.cc b/test/asan/TestCases/suppressions-library.cc
index ad6e09279b3dc..e95d339168ed8 100644
--- a/test/asan/TestCases/suppressions-library.cc
+++ b/test/asan/TestCases/suppressions-library.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_asan -O0 -DSHARED_LIB %s %fPIC -shared -o %dynamiclib %ld_flags_rpath_so
// RUN: %clangxx_asan -O0 %s -o %t %ld_flags_rpath_exe
// Check that without suppressions, we catch the issue.
diff --git a/test/asan/TestCases/use-after-delete.cc b/test/asan/TestCases/use-after-delete.cc
index 8fdec8d83c803..1cc8c2f079aca 100644
--- a/test/asan/TestCases/use-after-delete.cc
+++ b/test/asan/TestCases/use-after-delete.cc
@@ -2,8 +2,7 @@
// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
-// XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
+// REQUIRES: stable-runtime
#include <stdlib.h>
int main() {
diff --git a/test/asan/TestCases/use-after-free-right.cc b/test/asan/TestCases/use-after-free-right.cc
index f714b44f2f1f4..d72370e72d816 100644
--- a/test/asan/TestCases/use-after-free-right.cc
+++ b/test/asan/TestCases/use-after-free-right.cc
@@ -2,8 +2,7 @@
// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
-// XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
+// REQUIRES: stable-runtime
// Test use-after-free report in the case when access is at the right border of
// the allocation.
diff --git a/test/asan/TestCases/use-after-free.cc b/test/asan/TestCases/use-after-free.cc
index 7bc225b1ef863..c96d7f2e24e1f 100644
--- a/test/asan/TestCases/use-after-free.cc
+++ b/test/asan/TestCases/use-after-free.cc
@@ -2,8 +2,7 @@
// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
-// XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
+// REQUIRES: stable-runtime
#include <stdlib.h>
int main() {
diff --git a/test/asan/TestCases/use-after-scope-capture.cc b/test/asan/TestCases/use-after-scope-capture.cc
index 07aab672eecb3..113ce35366627 100644
--- a/test/asan/TestCases/use-after-scope-capture.cc
+++ b/test/asan/TestCases/use-after-scope-capture.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -std=c++11 -O1 -fsanitize-address-use-after-scope %s -o %t && \
+// RUN: %clangxx_asan %stdcxx11 -O1 -fsanitize-address-use-after-scope %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
#include <functional>
diff --git a/test/asan/TestCases/use-after-scope-chars.cc b/test/asan/TestCases/use-after-scope-chars.cc
deleted file mode 100644
index 51fc5fa387474..0000000000000
--- a/test/asan/TestCases/use-after-scope-chars.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \
-// RUN: not %run %t 2>&1 | FileCheck %s
-// XFAIL: *
-
-// FIXME: This works only for arraysize <= 8.
-
-char *p = 0;
-
-int main() {
- {
- char x[1024] = {};
- p = x;
- }
- return *p; // BOOM
-}
diff --git a/test/asan/TestCases/use-after-scope-goto.cc b/test/asan/TestCases/use-after-scope-goto.cc
new file mode 100644
index 0000000000000..351cbe995efb2
--- /dev/null
+++ b/test/asan/TestCases/use-after-scope-goto.cc
@@ -0,0 +1,73 @@
+// RUN: %clangxx_asan -O0 -fsanitize-address-use-after-scope %s -o %t && %run %t
+
+// Function jumps over variable initialization making lifetime analysis
+// ambiguous. Asan should ignore such variable and program must not fail.
+
+#include <stdlib.h>
+
+int *ptr;
+
+void f1(int cond) {
+ if (cond)
+ goto label;
+ int tmp;
+
+ label:
+ ptr = &tmp;
+ *ptr = 5;
+}
+
+void f2(int cond) {
+ switch (cond) {
+ case 1: {
+ ++cond;
+ int tmp;
+ ptr = &tmp;
+ exit(0);
+ case 2:
+ ptr = &tmp;
+ *ptr = 5;
+ exit(0);
+ }
+ }
+}
+
+void f3(int cond) {
+ {
+ int tmp;
+ goto l2;
+ l1:
+ ptr = &tmp;
+ *ptr = 5;
+
+ exit(0);
+ }
+ l2:
+ goto l1;
+}
+
+void use(int *x) {
+ static int c = 10;
+ if (--c == 0)
+ exit(0);
+ (*x)++;
+}
+
+void f4() {
+ {
+ int x;
+ l2:
+ use(&x);
+ goto l1;
+ }
+ l1:
+ goto l2;
+}
+
+int main() {
+ f1(1);
+ f2(1);
+ f3(1);
+ f4();
+ return 0;
+}
diff --git a/test/asan/TestCases/use-after-scope-inlined.cc b/test/asan/TestCases/use-after-scope-inlined.cc
index fc8c7f7bb87d8..98a455cbc0c7f 100644
--- a/test/asan/TestCases/use-after-scope-inlined.cc
+++ b/test/asan/TestCases/use-after-scope-inlined.cc
@@ -24,5 +24,5 @@ int main(int argc, char *argv[]) {
// CHECK: Address 0x{{.*}} is located in stack of thread T0 at offset
// CHECK: [[OFFSET:[^ ]*]] in frame
// CHECK: main
- // CHECK: {{\[}}[[OFFSET]], {{.*}}) 'x.i'
+ // CHECK: {{\[}}[[OFFSET]], {{.*}}) 'x.i:[[@LINE-15]]'
}
diff --git a/test/asan/TestCases/use-after-scope-loop-bug.cc b/test/asan/TestCases/use-after-scope-loop-bug.cc
index 6ad9bf3260ccd..d4b12eca9808f 100644
--- a/test/asan/TestCases/use-after-scope-loop-bug.cc
+++ b/test/asan/TestCases/use-after-scope-loop-bug.cc
@@ -1,10 +1,7 @@
// RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
-//
-// FIXME: @llvm.lifetime.* are not emitted for x.
-// XFAIL: *
-int *p;
+volatile int *p;
int main() {
// Variable goes in and out of scope.
@@ -13,4 +10,8 @@ int main() {
p = x + i;
}
return *p; // BOOM
+ // CHECK: ERROR: AddressSanitizer: stack-use-after-scope
+ // CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-loop-bug.cc:[[@LINE-2]]
+ // CHECK: Address 0x{{.*}} is located in stack of thread T{{.*}} at offset [[OFFSET:[^ ]+]] in frame
+ // {{\[}}[[OFFSET]], {{[0-9]+}}) 'x'
}
diff --git a/test/asan/TestCases/use-after-scope-loop-removed.cc b/test/asan/TestCases/use-after-scope-loop-removed.cc
index cd71a5046cd48..730bf3a3ebe33 100644
--- a/test/asan/TestCases/use-after-scope-loop-removed.cc
+++ b/test/asan/TestCases/use-after-scope-loop-removed.cc
@@ -1,9 +1,5 @@
// RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
-//
-// FIXME: Compiler removes for-loop but keeps x variable. For unknown reason
-// @llvm.lifetime.* are not emitted for x.
-// XFAIL: *
#include <stdlib.h>
@@ -14,6 +10,9 @@ int main() {
int x;
p = &x;
}
- return **p; // BOOM
+ return *p; // BOOM
// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
+ // CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-loop-removed.cc:[[@LINE-2]]
+ // CHECK: Address 0x{{.*}} is located in stack of thread T{{.*}} at offset [[OFFSET:[^ ]+]] in frame
+ // {{\[}}[[OFFSET]], {{[0-9]+}}) 'x'
}
diff --git a/test/asan/TestCases/use-after-scope-temp.cc b/test/asan/TestCases/use-after-scope-temp.cc
index 3736f914d0722..4dcef59a2ff12 100644
--- a/test/asan/TestCases/use-after-scope-temp.cc
+++ b/test/asan/TestCases/use-after-scope-temp.cc
@@ -1,8 +1,6 @@
-// RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \
+// RUN: %clangxx_asan %stdcxx11 -O1 -fsanitize-address-use-after-scope %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
-//
-// Lifetime for temporaries is not emitted yet.
-// XFAIL: *
+
struct IntHolder {
int val;
@@ -15,9 +13,9 @@ void save(const IntHolder &holder) {
}
int main(int argc, char *argv[]) {
- save({10});
+ save({argc});
int x = saved->val; // BOOM
-// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
-// CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-temp.cc:[[@LINE-2]]
+ // CHECK: ERROR: AddressSanitizer: stack-use-after-scope
+ // CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-temp.cc:[[@LINE-2]]
return x;
}
diff --git a/test/asan/TestCases/use-after-scope-temp2.cc b/test/asan/TestCases/use-after-scope-temp2.cc
new file mode 100644
index 0000000000000..1ecd3cbe23ff1
--- /dev/null
+++ b/test/asan/TestCases/use-after-scope-temp2.cc
@@ -0,0 +1,20 @@
+// RUN: %clangxx_asan %stdcxx11 -O1 -fsanitize-address-use-after-scope %s -o %t && \
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+
+struct IntHolder {
+ const IntHolder& Self() const {
+ return *this;
+ }
+ int val = 3;
+};
+
+const IntHolder *saved;
+
+int main(int argc, char *argv[]) {
+ saved = &IntHolder().Self();
+ int x = saved->val; // BOOM
+ // CHECK: ERROR: AddressSanitizer: stack-use-after-scope
+ // CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-temp2.cc:[[@LINE-2]]
+ return x;
+}
diff --git a/test/asan/TestCases/use-after-scope-types.cc b/test/asan/TestCases/use-after-scope-types.cc
new file mode 100644
index 0000000000000..ec6742bbb24fc
--- /dev/null
+++ b/test/asan/TestCases/use-after-scope-types.cc
@@ -0,0 +1,74 @@
+// RUN: %clangxx_asan %stdcxx11 -O0 -fsanitize-address-use-after-scope %s -o %t
+// RUN: not %run %t 0 2>&1 | FileCheck %s
+// RUN: not %run %t 1 2>&1 | FileCheck %s
+// RUN: not %run %t 2 2>&1 | FileCheck %s
+// RUN: not %run %t 3 2>&1 | FileCheck %s
+// RUN: not %run %t 4 2>&1 | FileCheck %s
+// RUN: not %run %t 5 2>&1 | FileCheck %s
+// RUN: not %run %t 6 2>&1 | FileCheck %s
+// RUN: not %run %t 7 2>&1 | FileCheck %s
+// RUN: not %run %t 8 2>&1 | FileCheck %s
+// RUN: not %run %t 9 2>&1 | FileCheck %s
+// RUN: not %run %t 10 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+#include <string>
+#include <vector>
+
+template <class T> struct Ptr {
+ void Store(T *ptr) { t = ptr; }
+
+ void Access() { *t = {}; }
+
+ T *t;
+};
+
+template <class T, size_t N> struct Ptr<T[N]> {
+ using Type = T[N];
+ void Store(Type *ptr) { t = *ptr; }
+
+ void Access() { *t = {}; }
+
+ T *t;
+};
+
+template <class T> __attribute__((noinline)) void test() {
+ Ptr<T> ptr;
+ {
+ T x;
+ ptr.Store(&x);
+ }
+
+ ptr.Access();
+ // CHECK: ERROR: AddressSanitizer: stack-use-after-scope
+ // CHECK: #{{[0-9]+}} 0x{{.*}} in {{(void )?test.*\((void)?\) .*}}use-after-scope-types.cc
+ // CHECK: Address 0x{{.*}} is located in stack of thread T{{.*}} at offset [[OFFSET:[^ ]+]] in frame
+ // {{\[}}[[OFFSET]], {{[0-9]+}}) 'x'
+}
+
+int main(int argc, char **argv) {
+ using Tests = void (*)();
+ Tests tests[] = {
+ &test<bool>,
+ &test<char>,
+ &test<int>,
+ &test<double>,
+ &test<float>,
+ &test<void*>,
+ &test<std::vector<std::string>>,
+ &test<int[3]>,
+ &test<int[1000]>,
+ &test<char[3]>,
+ &test<char[1000]>,
+ };
+
+ int n = atoi(argv[1]);
+ if (n == sizeof(tests) / sizeof(tests[0])) {
+ for (auto te : tests)
+ te();
+ } else {
+ tests[n]();
+ }
+
+ return 0;
+}
diff --git a/test/asan/TestCases/use-after-scope.cc b/test/asan/TestCases/use-after-scope.cc
index 1aa6758229dd1..d92dae6572cec 100644
--- a/test/asan/TestCases/use-after-scope.cc
+++ b/test/asan/TestCases/use-after-scope.cc
@@ -1,16 +1,17 @@
// RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
-int *p = 0;
+volatile int *p = 0;
int main() {
{
int x = 0;
p = &x;
}
- return *p; // BOOM
+ *p = 5; // BOOM
// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
// CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope.cc:[[@LINE-2]]
// CHECK: Address 0x{{.*}} is located in stack of thread T{{.*}} at offset [[OFFSET:[^ ]+]] in frame
// {{\[}}[[OFFSET]], {{[0-9]+}}) 'x'
+ return 0;
}
diff --git a/test/asan/TestCases/vla_chrome_testcase.cc b/test/asan/TestCases/vla_chrome_testcase.cc
index 8ee040120c48a..a8771800609d8 100644
--- a/test/asan/TestCases/vla_chrome_testcase.cc
+++ b/test/asan/TestCases/vla_chrome_testcase.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
+// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
//
diff --git a/test/asan/TestCases/vla_condition_overflow.cc b/test/asan/TestCases/vla_condition_overflow.cc
index 17f28d823252e..cf42d794e9d5a 100644
--- a/test/asan/TestCases/vla_condition_overflow.cc
+++ b/test/asan/TestCases/vla_condition_overflow.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
+// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
//
// REQUIRES: stable-runtime
diff --git a/test/asan/TestCases/vla_loop_overfow.cc b/test/asan/TestCases/vla_loop_overfow.cc
index 4f20c8d19d141..b6a5864c0f64b 100644
--- a/test/asan/TestCases/vla_loop_overfow.cc
+++ b/test/asan/TestCases/vla_loop_overfow.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
+// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
//
// REQUIRES: stable-runtime
diff --git a/test/asan/android_commands/android_run.py b/test/asan/android_commands/android_run.py
index 272d2110e5ade..f4ea52bec5880 100755
--- a/test/asan/android_commands/android_run.py
+++ b/test/asan/android_commands/android_run.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
-import os, sys, subprocess, tempfile
+import os, signal, sys, subprocess, tempfile
from android_common import *
ANDROID_TMPDIR = '/data/local/tmp/Output'
@@ -11,8 +11,7 @@ device_binary = os.path.join(ANDROID_TMPDIR, os.path.basename(sys.argv[0]))
def build_env():
args = []
# Android linker ignores RPATH. Set LD_LIBRARY_PATH to Output dir.
- args.append('LD_LIBRARY_PATH=%s:%s' %
- (ANDROID_TMPDIR, os.environ.get('LD_LIBRARY_PATH', '')))
+ args.append('LD_LIBRARY_PATH=%s' % (ANDROID_TMPDIR,))
for (key, value) in os.environ.items():
if key in ['ASAN_OPTIONS', 'ASAN_ACTIVATION_OPTIONS']:
args.append('%s="%s"' % (key, value))
@@ -34,4 +33,9 @@ if ret != 0:
sys.stdout.write(pull_from_device(device_stdout))
sys.stderr.write(pull_from_device(device_stderr))
-sys.exit(int(pull_from_device(device_exitcode)))
+retcode = int(pull_from_device(device_exitcode))
+# If the device process died with a signal, do abort().
+# Not exactly the same, but good enough to fool "not --crash".
+if retcode > 128:
+ os.kill(os.getpid(), signal.SIGABRT)
+sys.exit(retcode)
diff --git a/test/asan/lit.cfg b/test/asan/lit.cfg
index 894c3f859fbdb..1059f393ab34f 100644
--- a/test/asan/lit.cfg
+++ b/test/asan/lit.cfg
@@ -37,6 +37,12 @@ if config.host_os == 'Darwin':
# Also, make sure we do not overwhelm the syslog while testing.
default_asan_opts = 'abort_on_error=0'
default_asan_opts += ':log_to_syslog=0'
+elif config.android:
+ # The same as on Darwin, we default to "abort_on_error=1" which slows down
+ # testing. Also, all existing tests are using "not" instead of "not --crash"
+ # which does not work for abort()-terminated programs.
+ default_asan_opts = 'abort_on_error=0'
+
if default_asan_opts:
config.environment['ASAN_OPTIONS'] = default_asan_opts
default_asan_opts += ':'
@@ -77,14 +83,26 @@ if config.target_arch == 's390x':
clang_asan_static_cflags.append("-mbackchain")
clang_asan_static_cxxflags = config.cxx_mode_flags + clang_asan_static_cflags
+asan_dynamic_flags = []
if config.asan_dynamic:
- clang_asan_cflags = clang_asan_static_cflags + ['-shared-libasan']
- clang_asan_cxxflags = clang_asan_static_cxxflags + ['-shared-libasan']
+ asan_dynamic_flags = ["-shared-libasan"]
+ # On Windows, we need to simulate "clang-cl /MD" on the clang driver side.
+ if platform.system() == 'Windows':
+ asan_dynamic_flags += ["-D_MT", "-D_DLL", "-Wl,-nodefaultlib:libcmt,-defaultlib:msvcrt,-defaultlib:oldnames"]
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")
+clang_asan_cflags = clang_asan_static_cflags + asan_dynamic_flags
+clang_asan_cxxflags = clang_asan_static_cxxflags + asan_dynamic_flags
+
+# Add win32-(static|dynamic)-asan features to mark tests as passing or failing
+# in those modes. lit doesn't support logical feature test combinations.
+if platform.system() == 'Windows':
+ if config.asan_dynamic:
+ win_runtime_feature = "win32-dynamic-asan"
+ else:
+ win_runtime_feature = "win32-static-asan"
+ config.available_features.add(win_runtime_feature)
asan_lit_source_dir = get_required_attr(config, "asan_lit_source_dir")
if config.android == "1":
@@ -98,11 +116,16 @@ else:
def build_invocation(compile_flags):
return " " + " ".join([clang_wrapper, config.clang] + compile_flags) + " "
+# Clang driver link 'x86' (i686) architecture to 'i386'.
+target_arch = config.target_arch
+if (target_arch == "i686"):
+ target_arch = "i386"
+
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))
+config.substitutions.append( ("%shared_libasan", "libclang_rt.asan-%s.so" % 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)) )
@@ -124,6 +147,14 @@ if platform.system() == 'Windows':
config.substitutions.append( ("%asan_cxx_lib", base_lib % "_cxx") )
config.substitutions.append( ("%asan_dll_thunk", base_lib % "_dll_thunk") )
+if platform.system() == 'Windows':
+ # Don't use -std=c++11 on Windows, as the driver will detect the appropriate
+ # default needed to use with the STL.
+ config.substitutions.append(("%stdcxx11 ", ""))
+else:
+ # Some tests uses C++11 features such as lambdas and need to pass -std=c++11.
+ config.substitutions.append(("%stdcxx11 ", "-std=c++11 "))
+
# FIXME: De-hardcode this path.
asan_source_dir = os.path.join(
get_required_attr(config, "compiler_rt_src_root"), "lib", "asan")
@@ -186,12 +217,27 @@ if config.compiler_id == 'GNU':
libasan_dir = os.path.join(gcc_dir, "..", "lib" + config.bits)
push_dynamic_library_lookup_path(config, libasan_dir)
+# Add the RT libdir to PATH directly so that we can successfully run the gtest
+# binary to list its tests.
+if config.host_os == 'Windows' and config.asan_dynamic:
+ os.environ['PATH'] = os.path.pathsep.join([config.compiler_rt_libdir,
+ os.environ.get('PATH', '')])
+
# Default test suffixes.
config.suffixes = ['.c', '.cc', '.cpp']
if config.host_os == 'Darwin':
config.suffixes.append('.mm')
+if config.host_os == 'Windows':
+ config.substitutions.append(('%fPIC', ''))
+ config.substitutions.append(('%fPIE', ''))
+ config.substitutions.append(('%pie', ''))
+else:
+ config.substitutions.append(('%fPIC', '-fPIC'))
+ config.substitutions.append(('%fPIE', '-fPIE'))
+ config.substitutions.append(('%pie', '-pie'))
+
# Only run the tests on supported OSs.
if config.host_os not in ['Linux', 'Darwin', 'FreeBSD', 'Windows']:
config.unsupported = True
diff --git a/test/builtins/Unit/cpu_model_test.c b/test/builtins/Unit/cpu_model_test.c
index 5a918bde7dda8..6a170372d970d 100644
--- a/test/builtins/Unit/cpu_model_test.c
+++ b/test/builtins/Unit/cpu_model_test.c
@@ -11,6 +11,8 @@
//
//===----------------------------------------------------------------------===//
+// REQUIRES: x86-target-arch
+
int main (void) {
if(__builtin_cpu_supports("avx2"))
return 4;
diff --git a/test/builtins/Unit/negdf2vfp_test.c b/test/builtins/Unit/negdf2vfp_test.c
index f0e66777e3a11..f673b92cfc874 100644
--- a/test/builtins/Unit/negdf2vfp_test.c
+++ b/test/builtins/Unit/negdf2vfp_test.c
@@ -11,14 +11,15 @@
//
//===----------------------------------------------------------------------===//
+#include "int_lib.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
+#if __arm__
extern COMPILER_RT_ABI double __negdf2vfp(double a);
-#if __arm__
int test__negdf2vfp(double a)
{
double actual = __negdf2vfp(a);
diff --git a/test/builtins/Unit/subdf3vfp_test.c b/test/builtins/Unit/subdf3vfp_test.c
index 5d5d7117088f0..6e8d5a1aaa5ab 100644
--- a/test/builtins/Unit/subdf3vfp_test.c
+++ b/test/builtins/Unit/subdf3vfp_test.c
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "int_lib.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
diff --git a/test/cfi/CMakeLists.txt b/test/cfi/CMakeLists.txt
index 4c4debaf1a876..bd51eacb66754 100644
--- a/test/cfi/CMakeLists.txt
+++ b/test/cfi/CMakeLists.txt
@@ -11,16 +11,19 @@ configure_lit_site_cfg(
)
set(CFI_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+list(APPEND CFI_TEST_DEPS
+ ubsan
+ stats
+)
+if(COMPILER_RT_HAS_CFI)
+ list(APPEND CFI_TEST_DEPS cfi)
+endif()
+
if(NOT COMPILER_RT_STANDALONE_BUILD)
list(APPEND CFI_TEST_DEPS
opt
- ubsan
- stats
sanstats
)
- if(COMPILER_RT_HAS_CFI)
- list(APPEND CFI_TEST_DEPS cfi)
- endif()
if(LLVM_ENABLE_PIC AND LLVM_BINUTILS_INCDIR)
list(APPEND CFI_TEST_DEPS
LLVMgold
diff --git a/test/cfi/cross-dso/stats.cpp b/test/cfi/cross-dso/stats.cpp
index 3d25d7730c775..6566ea2fc2633 100644
--- a/test/cfi/cross-dso/stats.cpp
+++ b/test/cfi/cross-dso/stats.cpp
@@ -16,24 +16,24 @@ extern "C" void nvcall(A *a);
#ifdef SHARED_LIB
extern "C" __attribute__((noinline)) void vcall(A *a) {
- // CHECK: stats.cpp:[[@LINE+1]] vcall cfi-vcall 37
+ // CHECK: stats.cpp:[[@LINE+1]] vcall.cfi cfi-vcall 37
a->vf();
}
extern "C" __attribute__((noinline)) void nvcall(A *a) {
- // CHECK: stats.cpp:[[@LINE+1]] nvcall cfi-nvcall 51
+ // CHECK: stats.cpp:[[@LINE+1]] nvcall.cfi cfi-nvcall 51
a->nvf();
}
#else
extern "C" __attribute__((noinline)) A *dcast(A *a) {
- // CHECK: stats.cpp:[[@LINE+1]] dcast cfi-derived-cast 24
+ // CHECK: stats.cpp:[[@LINE+1]] dcast.cfi cfi-derived-cast 24
return (A *)(ABase *)a;
}
extern "C" __attribute__((noinline)) A *ucast(A *a) {
- // CHECK: stats.cpp:[[@LINE+1]] ucast cfi-unrelated-cast 81
+ // CHECK: stats.cpp:[[@LINE+1]] ucast.cfi cfi-unrelated-cast 81
return (A *)(char *)a;
}
diff --git a/test/cfi/icall/weak.c b/test/cfi/icall/weak.c
new file mode 100644
index 0000000000000..40739911109c8
--- /dev/null
+++ b/test/cfi/icall/weak.c
@@ -0,0 +1,15 @@
+// Test that weak symbols stay weak.
+// RUN: %clang_cfi -lm -o %t1 %s && %t1
+// XFAIL: darwin
+
+__attribute__((weak)) void does_not_exist(void);
+
+__attribute__((noinline))
+void foo(void (*p)(void)) {
+ p();
+}
+
+int main(int argc, char **argv) {
+ if (does_not_exist)
+ foo(does_not_exist);
+}
diff --git a/test/cfi/simple-fail.cpp b/test/cfi/simple-fail.cpp
index 92b1322718f89..595ca1617a02a 100644
--- a/test/cfi/simple-fail.cpp
+++ b/test/cfi/simple-fail.cpp
@@ -52,6 +52,9 @@
// RUN: %clangxx -o %t18 %s
// RUN: %t18 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %clangxx_cfi -DCHECK_NO_SANITIZE_CFI -o %t19 %s
+// RUN: %t19 2>&1 | FileCheck --check-prefix=NCFI %s
+
// Tests that the CFI mechanism crashes the program when making a virtual call
// to an object of the wrong class but with a compatible vtable, by casting a
// pointer to such an object and attempting to make a call through it.
@@ -73,6 +76,9 @@ struct B {
void B::f() {}
+#if defined(CHECK_NO_SANITIZE_CFI)
+__attribute__((no_sanitize("cfi")))
+#endif
int main() {
create_derivers<B>();
diff --git a/test/cfi/two-vcalls.cpp b/test/cfi/two-vcalls.cpp
new file mode 100644
index 0000000000000..854b3e0059c12
--- /dev/null
+++ b/test/cfi/two-vcalls.cpp
@@ -0,0 +1,60 @@
+// RUN: %clangxx_cfi_diag -o %t %s
+// RUN: %t 2>&1 | FileCheck %s
+
+// This test checks that we don't generate two type checks,
+// if two virtual calls are in the same function.
+
+// UNSUPPORTED: win32
+// REQUIRES: cxxabi
+
+// TODO(krasin): implement the optimization to not emit two type checks.
+// XFAIL: *
+#include <stdio.h>
+
+class Base {
+ public:
+ virtual void Foo() {
+ fprintf(stderr, "Base::Foo\n");
+ }
+
+ virtual void Bar() {
+ fprintf(stderr, "Base::Bar\n");
+ }
+};
+
+class Derived : public Base {
+ public:
+ void Foo() override {
+ fprintf(stderr, "Derived::Foo\n");
+ }
+
+ void Bar() override {
+ printf("Derived::Bar\n");
+ }
+};
+
+__attribute__((noinline)) void print(Base* ptr) {
+ ptr->Foo();
+ // Corrupt the vtable pointer. We expect that the optimization will
+ // check vtable before the first vcall then store it in a local
+ // variable, and reuse it for the second vcall. With no optimization,
+ // CFI will complain about the virtual table being corrupted.
+ *reinterpret_cast<void**>(ptr) = 0;
+ ptr->Bar();
+}
+
+
+int main() {
+ Base b;
+ Derived d;
+ // CHECK: Base::Foo
+ // CHECK: Base::Bar
+ print(&b);
+
+ // CHECK: Derived::Foo
+ // CHECK-NOT: runtime error
+ // CHECK: Derived::Bar
+ print(&d);
+
+ return 0;
+}
diff --git a/test/dfsan/CMakeLists.txt b/test/dfsan/CMakeLists.txt
index c2baf930d7685..04035faeddfe9 100644
--- a/test/dfsan/CMakeLists.txt
+++ b/test/dfsan/CMakeLists.txt
@@ -10,16 +10,7 @@ endif()
foreach(arch ${DFSAN_TEST_ARCH})
set(DFSAN_TEST_TARGET_ARCH ${arch})
string(TOLOWER "-${arch}" DFSAN_TEST_CONFIG_SUFFIX)
- if(ANDROID OR ${arch} MATCHES "arm|aarch64")
- # This is only true if we are cross-compiling.
- # Build all tests with host compiler and use host tools.
- set(DFSAN_TEST_TARGET_CC ${COMPILER_RT_TEST_COMPILER})
- set(DFSAN_TEST_TARGET_CFLAGS ${COMPILER_RT_TEST_COMPILER_CFLAGS})
- else()
- get_target_flags_for_arch(${arch} DFSAN_TEST_TARGET_CFLAGS)
- string(REPLACE ";" " " DFSAN_TEST_TARGET_CFLAGS "${DFSAN_TEST_TARGET_CFLAGS}")
- endif()
-
+ get_test_cc_for_arch(${arch} DFSAN_TEST_TARGET_CC DFSAN_TEST_TARGET_CFLAGS)
string(TOUPPER ${arch} ARCH_UPPER_CASE)
set(CONFIG_NAME ${ARCH_UPPER_CASE}Config)
diff --git a/test/dfsan/custom.cc b/test/dfsan/custom.cc
index 71422f7ce834f..c96d94053986e 100644
--- a/test/dfsan/custom.cc
+++ b/test/dfsan/custom.cc
@@ -3,6 +3,8 @@
// RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES %s -o %t && %run %t
// RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES -mllvm -dfsan-args-abi %s -o %t && %run %t
+// XFAIL: target-is-mips64el
+
// Tests custom implementations of various glibc functions.
#include <sanitizer/dfsan_interface.h>
diff --git a/test/dfsan/write_callback.c b/test/dfsan/write_callback.c
index 3ba027a0a46ae..31470efa9e879 100644
--- a/test/dfsan/write_callback.c
+++ b/test/dfsan/write_callback.c
@@ -3,6 +3,7 @@
// Tests that the custom implementation of write() does writes with or without
// a callback set using dfsan_set_write_callback().
+// REQUIRES: stable-runtime
#include <sanitizer/dfsan_interface.h>
diff --git a/test/esan/TestCases/mmap-shadow-conflict.c b/test/esan/TestCases/mmap-shadow-conflict.c
index 4b3c58b06825c..8e86bba4adb1e 100644
--- a/test/esan/TestCases/mmap-shadow-conflict.c
+++ b/test/esan/TestCases/mmap-shadow-conflict.c
@@ -1,26 +1,40 @@
// RUN: %clang_esan_frag -O0 %s -o %t 2>&1
-// RUN: %env_esan_opts=verbosity=1 %run %t 2>&1 | FileCheck %s
+// RUN: %env_esan_opts=verbosity=1 %run %t 2>&1 | FileCheck --check-prefix=%arch --check-prefix=CHECK %s
#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
int main(int argc, char **argv) {
+#if defined(__mips64)
+ void *Map = mmap((void *)0x0000001600000000ULL, 0x1000, PROT_READ,
+ MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
+#else
void *Map = mmap((void *)0x0000016000000000ULL, 0x1000, PROT_READ,
MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
+#endif
if (Map == (void *)-1)
fprintf(stderr, "map failed\n");
else
fprintf(stderr, "mapped %p\n", Map);
+#if defined(__mips64)
+ Map = mmap((void *)0x0000001600000000ULL, 0x1000, PROT_READ,
+ MAP_ANON|MAP_PRIVATE, -1, 0);
+#else
Map = mmap((void *)0x0000016000000000ULL, 0x1000, PROT_READ,
MAP_ANON|MAP_PRIVATE, -1, 0);
+#endif
fprintf(stderr, "mapped %p\n", Map);
// CHECK: in esan::initializeLibrary
// (There can be a re-exec for stack limit here.)
- // CHECK: Shadow scale=2 offset=0x440000000000
- // CHECK-NEXT: Shadow #0: [110000000000-114000000000) (256GB)
- // CHECK-NEXT: Shadow #1: [124000000000-12c000000000) (512GB)
- // CHECK-NEXT: Shadow #2: [148000000000-150000000000) (512GB)
+ // x86_64: Shadow scale=2 offset=0x440000000000
+ // x86_64-NEXT: Shadow #0: [110000000000-114000000000) (256GB)
+ // x86_64-NEXT: Shadow #1: [124000000000-12c000000000) (512GB)
+ // x86_64-NEXT: Shadow #2: [148000000000-150000000000) (512GB)
+ // mips64: Shadow scale=2 offset=0x4400000000
+ // mips64-NEXT: Shadow #0: [1140000000-1180000000) (1GB)
+ // mips64-NEXT: Shadow #1: [1380000000-13c0000000) (1GB)
+ // mips64-NEXT: Shadow #2: [14c0000000-1500000000) (1GB)
// CHECK-NEXT: mmap conflict: {{.*}}
// CHECK-NEXT: map failed
// CHECK-NEXT: mmap conflict: {{.*}}
diff --git a/test/esan/TestCases/struct-simple.cpp b/test/esan/TestCases/struct-simple.cpp
index c52154e094210..7ec9761fffa85 100644
--- a/test/esan/TestCases/struct-simple.cpp
+++ b/test/esan/TestCases/struct-simple.cpp
@@ -115,21 +115,21 @@ int main(int argc, char **argv) {
// CHECK: in esan::initializeCacheFrag
// CHECK-NEXT: in esan::processCompilationUnitInit
// CHECK-NEXT: in esan::processCacheFragCompilationUnitInit: {{.*}}struct-simple.cpp with 6 class(es)/struct(s)
- // CHECK-NEXT: Register struct.A#2#11#11: 2 fields
- // CHECK-NEXT: Register struct.B#2#3#2: 2 fields
- // CHECK-NEXT: Register union.U#1#3: 1 fields
- // CHECK-NEXT: Register struct.S#2#11#11: 2 fields
- // CHECK-NEXT: Register struct.D#3#14#11#11: 3 fields
- // CHECK-NEXT: Register struct.anon#3#11#11#11: 3 fields
+ // CHECK-NEXT: Register struct.A$2$11$11: 2 fields
+ // CHECK-NEXT: Register struct.B$2$3$2: 2 fields
+ // CHECK-NEXT: Register union.U$1$3: 1 fields
+ // CHECK-NEXT: Register struct.S$2$11$11: 2 fields
+ // CHECK-NEXT: Register struct.D$3$14$11$11: 3 fields
+ // CHECK-NEXT: Register struct.anon$3$11$11$11: 3 fields
// CHECK-NEXT: in esan::processCompilationUnitInit
// CHECK-NEXT: in esan::processCacheFragCompilationUnitInit: {{.*}}struct-simple.cpp with 0 class(es)/struct(s)
// CHECK-NEXT: in esan::processCompilationUnitInit
// CHECK-NEXT: in esan::processCacheFragCompilationUnitInit: {{.*}}struct-simple.cpp with 5 class(es)/struct(s)
- // CHECK-NEXT: Register class.C#3#14#13#13: 3 fields
- // CHECK-NEXT: Register struct.anon#2#11#11: 2 fields
- // CHECK-NEXT: Register union.anon#1#3: 1 fields
- // CHECK-NEXT: Duplicated struct.S#2#11#11: 2 fields
- // CHECK-NEXT: Register struct.D#3#11#11#11: 3 fields
+ // CHECK-NEXT: Register class.C$3$14$13$13: 3 fields
+ // CHECK-NEXT: Register struct.anon$2$11$11: 2 fields
+ // CHECK-NEXT: Register union.anon$1$3: 1 fields
+ // CHECK-NEXT: Duplicated struct.S$2$11$11: 2 fields
+ // CHECK-NEXT: Register struct.D$3$11$11$11: 3 fields
struct C c[2];
struct S s;
struct D d;
@@ -148,24 +148,24 @@ int main(int argc, char **argv) {
// CHECK-NEXT: in esan::finalizeCacheFrag
// CHECK-NEXT: in esan::processCompilationUnitExit
// CHECK-NEXT: in esan::processCacheFragCompilationUnitExit: {{.*}}struct-simple.cpp with 5 class(es)/struct(s)
- // CHECK-NEXT: Unregister class.C#3#14#13#13: 3 fields
+ // CHECK-NEXT: Unregister class.C$3$14$13$13: 3 fields
// CHECK-NEXT: {{.*}} class C
// CHECK-NEXT: {{.*}} size = 32, count = 5, ratio = 3, array access = 5
// CHECK-NEXT: {{.*}} # 0: offset = 0, size = 8, count = 2, type = %struct.anon = type { i32, i32 }
// CHECK-NEXT: {{.*}} # 1: offset = 8, size = 8, count = 2, type = %union.anon = type { double }
// CHECK-NEXT: {{.*}} # 2: offset = 16, size = 10, count = 1, type = [10 x i8]
- // CHECK-NEXT: Unregister struct.anon#2#11#11: 2 fields
+ // CHECK-NEXT: Unregister struct.anon$2$11$11: 2 fields
// CHECK-NEXT: {{.*}} struct anon
// CHECK-NEXT: {{.*}} size = 8, count = 2, ratio = 1, array access = 0
// CHECK-NEXT: {{.*}} # 0: offset = 0, size = 4, count = 1, type = i32
// CHECK-NEXT: {{.*}} # 1: offset = 4, size = 4, count = 1, type = i32
- // CHECK-NEXT: Unregister union.anon#1#3: 1 fields
- // CHECK-NEXT: Unregister struct.S#2#11#11: 2 fields
+ // CHECK-NEXT: Unregister union.anon$1$3: 1 fields
+ // CHECK-NEXT: Unregister struct.S$2$11$11: 2 fields
// CHECK-NEXT: {{.*}} struct S
// CHECK-NEXT: {{.*}} size = 8, count = 2, ratio = 2, array access = 0
// CHECK-NEXT: {{.*}} # 0: count = 2
// CHECK-NEXT: {{.*}} # 1: count = 0
- // CHECK-NEXT: Unregister struct.D#3#11#11#11: 3 fields
+ // CHECK-NEXT: Unregister struct.D$3$11$11$11: 3 fields
// CHECK-NEXT: {{.*}} struct D
// CHECK-NEXT: {{.*}} size = 12, count = 2, ratio = 2, array access = 0
// CHECK-NEXT: {{.*}} # 0: offset = 0, size = 4, count = 1, type = i32
@@ -175,25 +175,25 @@ int main(int argc, char **argv) {
// CHECK-NEXT: in esan::processCacheFragCompilationUnitExit: {{.*}}struct-simple.cpp with 0 class(es)/struct(s)
// CHECK-NEXT: in esan::processCompilationUnitExit
// CHECK-NEXT: in esan::processCacheFragCompilationUnitExit: {{.*}}struct-simple.cpp with 6 class(es)/struct(s)
- // CHECK-NEXT: Unregister struct.A#2#11#11: 2 fields
+ // CHECK-NEXT: Unregister struct.A$2$11$11: 2 fields
// CHECK-NEXT: {{.*}} struct A
// CHECK-NEXT: {{.*}} size = 8, count = 2049, ratio = 2048, array access = 0
// CHECK-NEXT: {{.*}} # 0: count = 2048
// CHECK-NEXT: {{.*}} # 1: count = 1
- // CHECK-NEXT: Unregister struct.B#2#3#2: 2 fields
+ // CHECK-NEXT: Unregister struct.B$2$3$2: 2 fields
// CHECK-NEXT: {{.*}} struct B
// CHECK-NEXT: {{.*}} size = 16, count = 2097153, ratio = 2097152, array access = 0
// CHECK-NEXT: {{.*}} # 0: count = 1
// CHECK-NEXT: {{.*}} # 1: count = 2097152
- // CHECK-NEXT: Unregister union.U#1#3: 1 fields
- // CHECK-NEXT: Duplicated struct.S#2#11#11: 2 fields
- // CHECK-NEXT: Unregister struct.D#3#14#11#11: 3 fields
+ // CHECK-NEXT: Unregister union.U$1$3: 1 fields
+ // CHECK-NEXT: Duplicated struct.S$2$11$11: 2 fields
+ // CHECK-NEXT: Unregister struct.D$3$14$11$11: 3 fields
// CHECK-NEXT: {{.*}} struct D
// CHECK-NEXT: {{.*}} size = 128, count = 2097153, ratio = 2097153, array access = 0
// CHECK-NEXT: {{.*}} # 0: count = 1
// CHECK-NEXT: {{.*}} # 1: count = 0
// CHECK-NEXT: {{.*}} # 2: count = 2097152
- // CHECK-NEXT: Unregister struct.anon#3#11#11#11: 3 fields
+ // CHECK-NEXT: Unregister struct.anon$3$11$11$11: 3 fields
// CHECK-NEXT: {{.*}} struct anon
// CHECK-NEXT: {{.*}} size = 12, count = 2097152, ratio = 4194304, array access = 2097152
// CHECK-NEXT: {{.*}} # 0: count = 0
diff --git a/test/esan/TestCases/verbose-simple.c b/test/esan/TestCases/verbose-simple.c
index 0d867bf55d9ef..5ac37e159295f 100644
--- a/test/esan/TestCases/verbose-simple.c
+++ b/test/esan/TestCases/verbose-simple.c
@@ -1,14 +1,18 @@
// RUN: %clang_esan_frag -O0 %s -o %t 2>&1
-// RUN: %env_esan_opts="verbosity=1 log_exe_name=1" %run %t 2>&1 | FileCheck %s
+// RUN: %env_esan_opts="verbosity=1 log_exe_name=1" %run %t 2>&1 | FileCheck --check-prefix=%arch --check-prefix=CHECK %s
int main(int argc, char **argv) {
// CHECK: in esan::initializeLibrary
// (There can be a re-exec for stack limit here.)
- // CHECK: Shadow scale=2 offset=0x440000000000
- // CHECK-NEXT: Shadow #0: [110000000000-114000000000) (256GB)
- // CHECK-NEXT: Shadow #1: [124000000000-12c000000000) (512GB)
- // CHECK-NEXT: Shadow #2: [148000000000-150000000000) (512GB)
- // CHECK-NEXT: in esan::finalizeLibrary
- // CHECK-NEXT: ==verbose-simple{{.*}}EfficiencySanitizer: total struct field access count = 0
+ // x86_64: Shadow scale=2 offset=0x440000000000
+ // x86_64-NEXT: Shadow #0: [110000000000-114000000000) (256GB)
+ // x86_64-NEXT: Shadow #1: [124000000000-12c000000000) (512GB)
+ // x86_64-NEXT: Shadow #2: [148000000000-150000000000) (512GB)
+ // mips64: Shadow scale=2 offset=0x4400000000
+ // mips64-NEXT: Shadow #0: [1140000000-1180000000) (1GB)
+ // mips64-NEXT: Shadow #1: [1380000000-13c0000000) (1GB)
+ // mips64-NEXT: Shadow #2: [14c0000000-1500000000) (1GB)
+ // CHECK: in esan::finalizeLibrary
+ // CHECK: ==verbose-simple{{.*}}EfficiencySanitizer: total struct field access count = 0
return 0;
}
diff --git a/test/esan/Unit/hashtable.cpp b/test/esan/Unit/hashtable.cpp
new file mode 100644
index 0000000000000..390a427da255b
--- /dev/null
+++ b/test/esan/Unit/hashtable.cpp
@@ -0,0 +1,179 @@
+// RUN: %clangxx_unit -esan-instrument-loads-and-stores=0 -O0 %s -o %t 2>&1
+// RUN: %env_esan_opts="record_snapshots=0" %run %t 2>&1 | FileCheck %s
+
+#include "esan/esan_hashtable.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+class MyData {
+ public:
+ MyData(const char *Str) : RefCount(0) { Buf = strdup(Str); }
+ ~MyData() {
+ fprintf(stderr, " Destructor: %s.\n", Buf);
+ free(Buf);
+ }
+ bool operator==(MyData &Cmp) { return strcmp(Buf, Cmp.Buf) == 0; }
+ operator size_t() const {
+ size_t Res = 0;
+ for (int i = 0; i < strlen(Buf); ++i)
+ Res ^= Buf[i];
+ return Res;
+ }
+ char *Buf;
+ int RefCount;
+};
+
+// We use a smart pointer wrapper to free the payload on hashtable removal.
+struct MyDataPayload {
+ MyDataPayload() : Data(nullptr) {}
+ explicit MyDataPayload(MyData *Data) : Data(Data) { ++Data->RefCount; }
+ ~MyDataPayload() {
+ if (Data && --Data->RefCount == 0) {
+ fprintf(stderr, "Deleting %s.\n", Data->Buf);
+ delete Data;
+ }
+ }
+ MyDataPayload(const MyDataPayload &Copy) {
+ Data = Copy.Data;
+ ++Data->RefCount;
+ }
+ MyDataPayload & operator=(const MyDataPayload &Copy) {
+ if (this != &Copy) {
+ this->~MyDataPayload();
+ Data = Copy.Data;
+ ++Data->RefCount;
+ }
+ return *this;
+ }
+ bool operator==(MyDataPayload &Cmp) { return *Data == *Cmp.Data; }
+ operator size_t() const { return (size_t)*Data; }
+ MyData *Data;
+};
+
+int main()
+{
+ __esan::HashTable<int, int> IntTable;
+ assert(IntTable.size() == 0);
+
+ // Test iteration on an empty table.
+ int Count = 0;
+ for (auto Iter = IntTable.begin(); Iter != IntTable.end();
+ ++Iter, ++Count) {
+ // Empty.
+ }
+ assert(Count == 0);
+
+ bool Added = IntTable.add(4, 42);
+ assert(Added);
+ assert(!IntTable.add(4, 42));
+ assert(IntTable.size() == 1);
+ int Value;
+ bool Found = IntTable.lookup(4, Value);
+ assert(Found && Value == 42);
+
+ // Test iterator.
+ IntTable.lock();
+ for (auto Iter = IntTable.begin(); Iter != IntTable.end();
+ ++Iter, ++Count) {
+ assert((*Iter).Key == 4);
+ assert((*Iter).Data == 42);
+ }
+ IntTable.unlock();
+ assert(Count == 1);
+ assert(Count == IntTable.size());
+ assert(!IntTable.remove(5));
+ assert(IntTable.remove(4));
+
+ // Test a more complex payload.
+ __esan::HashTable<int, MyDataPayload> DataTable(4);
+ MyDataPayload NewData(new MyData("mystring"));
+ Added = DataTable.add(4, NewData);
+ assert(Added);
+ MyDataPayload FoundData;
+ Found = DataTable.lookup(4, FoundData);
+ assert(Found && strcmp(FoundData.Data->Buf, "mystring") == 0);
+ assert(!DataTable.remove(5));
+ assert(DataTable.remove(4));
+ // Test resize.
+ for (int i = 0; i < 4; ++i) {
+ MyDataPayload MoreData(new MyData("delete-at-end"));
+ Added = DataTable.add(i+1, MoreData);
+ assert(Added);
+ assert(!DataTable.add(i+1, MoreData));
+ }
+ for (int i = 0; i < 4; ++i) {
+ Found = DataTable.lookup(i+1, FoundData);
+ assert(Found && strcmp(FoundData.Data->Buf, "delete-at-end") == 0);
+ }
+ DataTable.lock();
+ Count = 0;
+ for (auto Iter = DataTable.begin(); Iter != DataTable.end();
+ ++Iter, ++Count) {
+ int Key = (*Iter).Key;
+ FoundData = (*Iter).Data;
+ assert(Key >= 1 && Key <= 4);
+ assert(strcmp(FoundData.Data->Buf, "delete-at-end") == 0);
+ }
+ DataTable.unlock();
+ assert(Count == 4);
+ assert(Count == DataTable.size());
+
+ // Ensure the iterator supports a range-based for loop.
+ DataTable.lock();
+ Count = 0;
+ for (auto Pair : DataTable) {
+ assert(Pair.Key >= 1 && Pair.Key <= 4);
+ assert(strcmp(Pair.Data.Data->Buf, "delete-at-end") == 0);
+ ++Count;
+ }
+ DataTable.unlock();
+ assert(Count == 4);
+ assert(Count == DataTable.size());
+
+ // Test payload freeing via smart pointer wrapper.
+ __esan::HashTable<MyDataPayload, MyDataPayload, true> DataKeyTable;
+ MyDataPayload DataA(new MyData("string AB"));
+ DataKeyTable.lock();
+ Added = DataKeyTable.add(DataA, DataA);
+ assert(Added);
+ Found = DataKeyTable.lookup(DataA, FoundData);
+ assert(Found && strcmp(FoundData.Data->Buf, "string AB") == 0);
+ MyDataPayload DataB(new MyData("string AB"));
+ Added = DataKeyTable.add(DataB, DataB);
+ assert(!Added);
+ DataKeyTable.remove(DataB); // Should free the DataA payload.
+ DataKeyTable.unlock();
+
+ // Test custom functors.
+ struct CustomHash {
+ size_t operator()(int Key) const { return Key % 4; }
+ };
+ struct CustomEqual {
+ bool operator()(int Key1, int Key2) const { return Key1 %4 == Key2 % 4; }
+ };
+ __esan::HashTable<int, int, false, CustomHash, CustomEqual> ModTable;
+ Added = ModTable.add(2, 42);
+ assert(Added);
+ Added = ModTable.add(6, 42);
+ assert(!Added);
+
+ fprintf(stderr, "All checks passed.\n");
+ return 0;
+}
+// CHECK: Deleting mystring.
+// CHECK-NEXT: Destructor: mystring.
+// CHECK-NEXT: All checks passed.
+// CHECK-NEXT: Deleting string AB.
+// CHECK-NEXT: Destructor: string AB.
+// CHECK-NEXT: Deleting string AB.
+// CHECK-NEXT: Destructor: string AB.
+// CHECK-NEXT: Deleting delete-at-end.
+// CHECK-NEXT: Destructor: delete-at-end.
+// CHECK-NEXT: Deleting delete-at-end.
+// CHECK-NEXT: Destructor: delete-at-end.
+// CHECK-NEXT: Deleting delete-at-end.
+// CHECK-NEXT: Destructor: delete-at-end.
+// CHECK-NEXT: Deleting delete-at-end.
+// CHECK-NEXT: Destructor: delete-at-end.
diff --git a/test/esan/lit.cfg b/test/esan/lit.cfg
index cf16a6b5df44b..8b8457d66e00d 100644
--- a/test/esan/lit.cfg
+++ b/test/esan/lit.cfg
@@ -40,5 +40,5 @@ config.substitutions.append(('%env_esan_opts=',
config.suffixes = ['.c', '.cpp']
# EfficiencySanitizer tests are currently supported on Linux x86-64 only.
-if config.host_os not in ['Linux'] or config.target_arch != 'x86_64':
+if config.host_os not in ['Linux'] or config.target_arch not in ['x86_64', 'mips64'] :
config.unsupported = True
diff --git a/test/interception/CMakeLists.txt b/test/interception/CMakeLists.txt
new file mode 100644
index 0000000000000..ff9e4b0adb86d
--- /dev/null
+++ b/test/interception/CMakeLists.txt
@@ -0,0 +1,17 @@
+set(INTERCEPTION_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+set(INTERCEPTION_TESTSUITES)
+
+# Unit tests. There are currently no unit tests capable to running on Apple or
+# Android targets.
+if(COMPILER_RT_INCLUDE_TESTS AND NOT ANDROID AND NOT APPLE)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg)
+ list(APPEND INTERCEPTION_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit)
+ list(APPEND INTERCEPTION_TEST_DEPS InterceptionUnitTests)
+endif()
+
+add_lit_testsuite(check-interception "Running the Interception tests"
+ ${INTERCEPTION_TESTSUITES}
+ DEPENDS ${INTERCEPTION_TEST_DEPS})
+set_target_properties(check-interception PROPERTIES FOLDER "Compiler-RT Misc")
diff --git a/test/interception/Unit/lit.site.cfg.in b/test/interception/Unit/lit.site.cfg.in
new file mode 100644
index 0000000000000..5d3e2f94f8ac7
--- /dev/null
+++ b/test/interception/Unit/lit.site.cfg.in
@@ -0,0 +1,14 @@
+@LIT_SITE_CFG_IN_HEADER@
+
+# Load common config for all compiler-rt unit tests.
+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/unittests/lit.common.unit.configured")
+
+# Setup config name.
+config.name = 'Interception-Unit'
+
+# Setup test source and exec root. For unit tests, we define
+# it as build directory with interception tests.
+# FIXME: De-hardcode this path.
+config.test_exec_root = os.path.join("@COMPILER_RT_BINARY_DIR@", "lib",
+ "interception", "tests")
+config.test_source_root = config.test_exec_root
diff --git a/test/lit.common.cfg b/test/lit.common.cfg
index f19fde2f89eb0..1048c46f11bcb 100644
--- a/test/lit.common.cfg
+++ b/test/lit.common.cfg
@@ -52,7 +52,8 @@ possibly_dangerous_env_vars = ['ASAN_OPTIONS', 'DFSAN_OPTIONS', 'LSAN_OPTIONS',
'LIBCLANG_LOGGING', 'LIBCLANG_BGPRIO_INDEX',
'LIBCLANG_BGPRIO_EDIT', 'LIBCLANG_NOTHREADS',
'LIBCLANG_RESOURCE_USAGE',
- 'LIBCLANG_CODE_COMPLETION_LOGGING']
+ 'LIBCLANG_CODE_COMPLETION_LOGGING',
+ 'XRAY_OPTIONS']
# Clang/Win32 may refer to %INCLUDE%. vsvarsall.bat sets it.
if platform.system() != 'Windows':
possibly_dangerous_env_vars.append('INCLUDE')
@@ -87,6 +88,9 @@ config.substitutions.append( ('%run', config.emulator) )
# Define CHECK-%os to check for OS-dependent output.
config.substitutions.append( ('CHECK-%os', ("CHECK-" + config.host_os)))
+# Define %arch to check for architecture-dependent output.
+config.substitutions.append( ('%arch', (config.host_arch)))
+
if config.host_os == 'Windows':
# FIXME: This isn't quite right. Specifically, it will succeed if the program
# does not crash but exits with a non-zero exit code. We ought to merge
@@ -103,6 +107,7 @@ if target_arch:
config.available_features.add(target_arch + '-target-arch')
if target_arch in ['x86_64', 'i386', 'i686']:
config.available_features.add('x86-target-arch')
+ config.available_features.add(target_arch + '-' + config.host_os.lower())
compiler_rt_debug = getattr(config, 'compiler_rt_debug', False)
if not compiler_rt_debug:
@@ -136,6 +141,10 @@ if config.host_os == 'Darwin':
except:
pass
+ config.substitutions.append( ("%macos_min_target_10_11", "-mmacosx-version-min=10.11") )
+else:
+ config.substitutions.append( ("%macos_min_target_10_11", "") )
+
sancovcc_path = os.path.join(llvm_tools_dir, "sancov")
if os.path.exists(sancovcc_path):
config.available_features.add("has_sancovcc")
@@ -148,7 +157,7 @@ def is_linux_lto_supported():
if not os.path.exists(os.path.join(config.llvm_shlib_dir, 'LLVMgold.so')):
return False
- ld_cmd = subprocess.Popen([config.gold_executable, '--help'], stdout = subprocess.PIPE)
+ ld_cmd = subprocess.Popen([config.gold_executable, '--help'], stdout = subprocess.PIPE, env={'LANG': 'C'})
ld_out = ld_cmd.stdout.read().decode()
ld_cmd.wait()
@@ -175,6 +184,9 @@ elif config.host_os == 'Windows' and is_windows_lto_supported():
else:
config.lto_supported = False
+if config.lto_supported:
+ config.available_features.add('lto')
+
# Ask llvm-config about assertion mode.
try:
llvm_config_cmd = subprocess.Popen(
diff --git a/test/lit.common.configured.in b/test/lit.common.configured.in
index 35aa78c984f09..862d06bf2947d 100644
--- a/test/lit.common.configured.in
+++ b/test/lit.common.configured.in
@@ -17,7 +17,7 @@ set_default("llvm_obj_root", "@LLVM_BINARY_DIR@")
set_default("compiler_rt_src_root", "@COMPILER_RT_SOURCE_DIR@")
set_default("compiler_rt_obj_root", "@COMPILER_RT_BINARY_DIR@")
set_default("llvm_tools_dir", "@LLVM_TOOLS_BINARY_DIR@")
-set_default("llvm_shlib_dir", "@SHLIBDIR@")
+set_default("llvm_shlib_dir", "@LLVM_LIBRARY_OUTPUT_INTDIR@")
set_default("gold_executable", "@GOLD_EXECUTABLE@")
set_default("clang", "@COMPILER_RT_TEST_COMPILER@")
set_default("compiler_id", "@COMPILER_RT_TEST_COMPILER_ID@")
@@ -28,6 +28,7 @@ set_default("emulator", "@COMPILER_RT_EMULATOR@")
set_default("sanitizer_can_use_cxxabi", @SANITIZER_CAN_USE_CXXABI_PYBOOL@)
set_default("has_lld", @COMPILER_RT_HAS_LLD_SOURCES_PYBOOL@)
set_default("can_symbolize", @CAN_SYMBOLIZE@)
+config.available_features.add('target-is-%s' % config.target_arch)
# LLVM tools dir can be passed in lit parameters, so try to
# apply substitution.
diff --git a/test/lsan/CMakeLists.txt b/test/lsan/CMakeLists.txt
index e3d363a1f2759..3324928ddb1c1 100644
--- a/test/lsan/CMakeLists.txt
+++ b/test/lsan/CMakeLists.txt
@@ -10,16 +10,7 @@ endif()
foreach(arch ${LSAN_TEST_ARCH})
set(LSAN_TEST_TARGET_ARCH ${arch})
string(TOLOWER "-${arch}" LSAN_TEST_CONFIG_SUFFIX)
- if(ANDROID OR ${arch} MATCHES "arm|aarch64")
- # This is only true if we are cross-compiling.
- # Build all tests with host compiler and use host tools.
- set(LSAN_TEST_TARGET_CC ${COMPILER_RT_TEST_COMPILER})
- set(LSAN_TEST_TARGET_CFLAGS ${COMPILER_RT_TEST_COMPILER_CFLAGS})
- else()
- get_target_flags_for_arch(${arch} LSAN_TEST_TARGET_CFLAGS)
- string(REPLACE ";" " " LSAN_TEST_TARGET_CFLAGS "${LSAN_TEST_TARGET_CFLAGS}")
- endif()
-
+ get_test_cc_for_arch(${arch} LSAN_TEST_TARGET_CC LSAN_TEST_TARGET_CFLAGS)
string(TOUPPER ${arch} ARCH_UPPER_CASE)
set(LSAN_LIT_TEST_MODE "Standalone")
set(CONFIG_NAME ${ARCH_UPPER_CASE}LsanConfig)
diff --git a/test/lsan/TestCases/cleanup_in_tsd_destructor.c b/test/lsan/TestCases/cleanup_in_tsd_destructor.c
index debf05c20473f..6da759563451c 100644
--- a/test/lsan/TestCases/cleanup_in_tsd_destructor.c
+++ b/test/lsan/TestCases/cleanup_in_tsd_destructor.c
@@ -14,6 +14,7 @@
#include <stdlib.h>
#include "sanitizer/lsan_interface.h"
+#include "sanitizer_common/print_address.h"
pthread_key_t key;
__thread void *p;
@@ -25,7 +26,7 @@ void key_destructor(void *arg) {
void *thread_func(void *arg) {
p = malloc(1337);
- fprintf(stderr, "Test alloc: %p.\n", p);
+ print_address("Test alloc: ", 1, p);
int res = pthread_setspecific(key, (void*)1);
assert(res == 0);
return 0;
@@ -41,5 +42,5 @@ int main() {
assert(res == 0);
return 0;
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: [[ADDR]] (1337 bytes)
diff --git a/test/lsan/TestCases/guard-page.c b/test/lsan/TestCases/guard-page.c
index 5c70a9f08aca5..25d63e2720c3a 100644
--- a/test/lsan/TestCases/guard-page.c
+++ b/test/lsan/TestCases/guard-page.c
@@ -22,6 +22,7 @@ static void die(const char* msg, int err) {
static void ctxfunc() {
pthread_mutex_lock(&mutex);
ctxfunc_started = 1;
+ // printf("ctxfunc\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
// Leave this context alive when the program exits.
@@ -35,11 +36,11 @@ static void* thread(void* arg) {
if (getcontext(&ctx) < 0)
die("getcontext", 0);
- stack = malloc(1 << 10);
+ stack = malloc(1 << 11);
if (stack == NULL)
die("malloc", 0);
ctx.uc_stack.ss_sp = stack;
- ctx.uc_stack.ss_size = 1 << 10;
+ ctx.uc_stack.ss_size = 1 << 11;
makecontext(&ctx, ctxfunc, 0);
setcontext(&ctx);
die("setcontext", 0);
diff --git a/test/lsan/TestCases/large_allocation_leak.cc b/test/lsan/TestCases/large_allocation_leak.cc
index f41143a8a501d..9d5698c9f8a65 100644
--- a/test/lsan/TestCases/large_allocation_leak.cc
+++ b/test/lsan/TestCases/large_allocation_leak.cc
@@ -5,14 +5,15 @@
#include <stdio.h>
#include <stdlib.h>
+#include "sanitizer_common/print_address.h"
int main() {
// maxsize in primary allocator is always less than this (1 << 25).
void *large_alloc = malloc(33554432);
- fprintf(stderr, "Test alloc: %p.\n", large_alloc);
+ print_address("Test alloc: ", 1, large_alloc);
return 0;
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (33554432 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
diff --git a/test/lsan/TestCases/pointer_to_self.cc b/test/lsan/TestCases/pointer_to_self.cc
index 63bde2ccf35df..40c122811f181 100644
--- a/test/lsan/TestCases/pointer_to_self.cc
+++ b/test/lsan/TestCases/pointer_to_self.cc
@@ -6,13 +6,14 @@
#include <stdio.h>
#include <stdlib.h>
+#include "sanitizer_common/print_address.h"
int main() {
void *p = malloc(1337);
*reinterpret_cast<void **>(p) = p;
- fprintf(stderr, "Test alloc: %p.\n", p);
+ print_address("Test alloc: ", 1, p);
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
diff --git a/test/lsan/TestCases/stale_stack_leak.cc b/test/lsan/TestCases/stale_stack_leak.cc
index 4b8a54edf4cc5..770096b088883 100644
--- a/test/lsan/TestCases/stale_stack_leak.cc
+++ b/test/lsan/TestCases/stale_stack_leak.cc
@@ -6,6 +6,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "sanitizer_common/print_address.h"
void **pp;
@@ -18,7 +19,7 @@ void *PutPointerOnStaleStack(void *p) {
void *locals[2048];
locals[0] = p;
pp = &locals[0];
- fprintf(stderr, "Test alloc: %p.\n", locals[0]);
+ print_address("Test alloc: ", 1, locals[0]);
return 0;
}
@@ -33,11 +34,11 @@ int main() {
__attribute__((destructor))
__attribute__((no_sanitize_address))
void ConfirmPointerHasSurvived() {
- fprintf(stderr, "Value after LSan: %p.\n", *pp);
+ print_address("Value after LSan: ", 1, *pp);
}
-// CHECK: Test alloc: [[ADDR:.*]].
-// CHECK-sanity: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
+// CHECK-sanity: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
-// CHECK-sanity: Value after LSan: [[ADDR]].
+// CHECK-sanity: Value after LSan: [[ADDR]]
diff --git a/test/lsan/TestCases/strace_test.cc b/test/lsan/TestCases/strace_test.cc
new file mode 100644
index 0000000000000..b3568d0b44e80
--- /dev/null
+++ b/test/lsan/TestCases/strace_test.cc
@@ -0,0 +1,14 @@
+// Test that lsan reports a proper error when running under strace.
+// RUN: %clangxx_lsan %s -o %t
+// RUN: not strace -o /dev/null %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static volatile void *sink;
+
+int main() {
+ sink = malloc(42);
+}
+// CHECK: LeakSanitizer has encountered a fatal error
+// CHECK: HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)
diff --git a/test/lsan/TestCases/use_after_return.cc b/test/lsan/TestCases/use_after_return.cc
index eb917c01ea80b..ed9cc785f0f5c 100644
--- a/test/lsan/TestCases/use_after_return.cc
+++ b/test/lsan/TestCases/use_after_return.cc
@@ -8,16 +8,17 @@
#include <stdio.h>
#include <stdlib.h>
+#include "sanitizer_common/print_address.h"
int main() {
void *stack_var = malloc(1337);
- fprintf(stderr, "Test alloc: %p.\n", stack_var);
+ print_address("Test alloc: ", 1, stack_var);
// Take pointer to variable, to ensure it's not optimized into a register.
- fprintf(stderr, "Stack var at: %p.\n", &stack_var);
+ print_address("Stack var at: ", 1, &stack_var);
// Do not return from main to prevent the pointer from going out of scope.
exit(0);
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
diff --git a/test/lsan/TestCases/use_globals_initialized.cc b/test/lsan/TestCases/use_globals_initialized.cc
index 172d22a9f0564..45c12dc4e120b 100644
--- a/test/lsan/TestCases/use_globals_initialized.cc
+++ b/test/lsan/TestCases/use_globals_initialized.cc
@@ -7,15 +7,16 @@
#include <stdio.h>
#include <stdlib.h>
+#include "sanitizer_common/print_address.h"
void *data_var = (void *)1;
int main() {
data_var = malloc(1337);
- fprintf(stderr, "Test alloc: %p.\n", data_var);
+ print_address("Test alloc: ", 1, data_var);
return 0;
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
diff --git a/test/lsan/TestCases/use_globals_uninitialized.cc b/test/lsan/TestCases/use_globals_uninitialized.cc
index 2daa661611f42..c198fcc7cbbb1 100644
--- a/test/lsan/TestCases/use_globals_uninitialized.cc
+++ b/test/lsan/TestCases/use_globals_uninitialized.cc
@@ -7,15 +7,16 @@
#include <stdio.h>
#include <stdlib.h>
+#include "sanitizer_common/print_address.h"
void *bss_var;
int main() {
bss_var = malloc(1337);
- fprintf(stderr, "Test alloc: %p.\n", bss_var);
+ print_address("Test alloc: ", 1, bss_var);
return 0;
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
diff --git a/test/lsan/TestCases/use_poisoned_asan.cc b/test/lsan/TestCases/use_poisoned_asan.cc
index a1c544c55f288..5acceeb8ce0a2 100644
--- a/test/lsan/TestCases/use_poisoned_asan.cc
+++ b/test/lsan/TestCases/use_poisoned_asan.cc
@@ -9,17 +9,18 @@
#include <stdlib.h>
#include <sanitizer/asan_interface.h>
#include <assert.h>
+#include "sanitizer_common/print_address.h"
void **p;
int main() {
p = new void *;
*p = malloc(1337);
- fprintf(stderr, "Test alloc: %p.\n", *p);
+ print_address("Test alloc: ", 1, *p);
__asan_poison_memory_region(p, sizeof(*p));
return 0;
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: AddressSanitizer:
diff --git a/test/lsan/TestCases/use_registers.cc b/test/lsan/TestCases/use_registers.cc
index 74301a26c32c6..7647679f4796c 100644
--- a/test/lsan/TestCases/use_registers.cc
+++ b/test/lsan/TestCases/use_registers.cc
@@ -10,6 +10,7 @@
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
+#include "sanitizer_common/print_address.h"
extern "C"
void *registers_thread_func(void *arg) {
@@ -35,7 +36,7 @@ void *registers_thread_func(void *arg) {
#else
#error "Test is not supported on this architecture."
#endif
- fprintf(stderr, "Test alloc: %p.\n", p);
+ print_address("Test alloc: ", 1, p);
fflush(stderr);
__sync_fetch_and_xor(sync, 1);
while (true)
@@ -51,7 +52,7 @@ int main() {
sched_yield();
return 0;
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
diff --git a/test/lsan/TestCases/use_stacks.cc b/test/lsan/TestCases/use_stacks.cc
index 7afcde15c733c..c32af68412606 100644
--- a/test/lsan/TestCases/use_stacks.cc
+++ b/test/lsan/TestCases/use_stacks.cc
@@ -7,14 +7,15 @@
#include <stdio.h>
#include <stdlib.h>
+#include "sanitizer_common/print_address.h"
int main() {
void *stack_var = malloc(1337);
- fprintf(stderr, "Test alloc: %p.\n", stack_var);
+ print_address("Test alloc: ", 1, stack_var);
// Do not return from main to prevent the pointer from going out of scope.
exit(0);
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
diff --git a/test/lsan/TestCases/use_stacks_threaded.cc b/test/lsan/TestCases/use_stacks_threaded.cc
index a1d4383e95696..ac1fb466fa030 100644
--- a/test/lsan/TestCases/use_stacks_threaded.cc
+++ b/test/lsan/TestCases/use_stacks_threaded.cc
@@ -10,12 +10,13 @@
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
+#include "sanitizer_common/print_address.h"
extern "C"
void *stacks_thread_func(void *arg) {
int *sync = reinterpret_cast<int *>(arg);
void *p = malloc(1337);
- fprintf(stderr, "Test alloc: %p.\n", p);
+ print_address("Test alloc: ", 1, p);
fflush(stderr);
__sync_fetch_and_xor(sync, 1);
while (true)
@@ -31,7 +32,7 @@ int main() {
sched_yield();
return 0;
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
diff --git a/test/lsan/TestCases/use_tls_dynamic.cc b/test/lsan/TestCases/use_tls_dynamic.cc
index 207894b0fffd4..927c5c4f768ea 100644
--- a/test/lsan/TestCases/use_tls_dynamic.cc
+++ b/test/lsan/TestCases/use_tls_dynamic.cc
@@ -12,6 +12,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string>
+#include "sanitizer_common/print_address.h"
int main(int argc, char *argv[]) {
std::string path = std::string(argv[0]) + "-so.so";
@@ -26,10 +27,10 @@ int main(int argc, char *argv[]) {
// If we don't know about dynamic TLS, we will return a false leak above.
void **p_in_tls = StoreToTLS(p);
assert(*p_in_tls == p);
- fprintf(stderr, "Test alloc: %p.\n", p);
+ print_address("Test alloc: ", 1, p);
return 0;
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
diff --git a/test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc b/test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc
index 14883712e6083..9ab4e1cdbc0e5 100644
--- a/test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc
+++ b/test/lsan/TestCases/use_tls_pthread_specific_dynamic.cc
@@ -9,6 +9,7 @@
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
+#include "sanitizer_common/print_address.h"
// From glibc: this many keys are stored in the thread descriptor directly.
const unsigned PTHREAD_KEY_2NDLEVEL_SIZE = 32;
@@ -28,10 +29,10 @@ int main() {
void *p = malloc(1337);
res = pthread_setspecific(key, p);
assert(res == 0);
- fprintf(stderr, "Test alloc: %p.\n", p);
+ print_address("Test alloc: ", 1, p);
return 0;
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
diff --git a/test/lsan/TestCases/use_tls_pthread_specific_static.cc b/test/lsan/TestCases/use_tls_pthread_specific_static.cc
index 1fd5681b60808..be0bcf6287548 100644
--- a/test/lsan/TestCases/use_tls_pthread_specific_static.cc
+++ b/test/lsan/TestCases/use_tls_pthread_specific_static.cc
@@ -9,6 +9,7 @@
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
+#include "sanitizer_common/print_address.h"
// From glibc: this many keys are stored in the thread descriptor directly.
const unsigned PTHREAD_KEY_2NDLEVEL_SIZE = 32;
@@ -22,10 +23,10 @@ int main() {
void *p = malloc(1337);
res = pthread_setspecific(key, p);
assert(res == 0);
- fprintf(stderr, "Test alloc: %p.\n", p);
+ print_address("Test alloc: ", 1, p);
return 0;
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
diff --git a/test/lsan/TestCases/use_tls_static.cc b/test/lsan/TestCases/use_tls_static.cc
index 50db23abb825a..5ffaf166bcd5d 100644
--- a/test/lsan/TestCases/use_tls_static.cc
+++ b/test/lsan/TestCases/use_tls_static.cc
@@ -7,15 +7,16 @@
#include <stdio.h>
#include <stdlib.h>
+#include "sanitizer_common/print_address.h"
__thread void *tls_var;
int main() {
tls_var = malloc(1337);
- fprintf(stderr, "Test alloc: %p.\n", tls_var);
+ print_address("Test alloc: ", 1, tls_var);
return 0;
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
diff --git a/test/lsan/TestCases/use_unaligned.cc b/test/lsan/TestCases/use_unaligned.cc
index 3e43ed4c092cb..86c3ed5200a36 100644
--- a/test/lsan/TestCases/use_unaligned.cc
+++ b/test/lsan/TestCases/use_unaligned.cc
@@ -7,17 +7,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "sanitizer_common/print_address.h"
void *arr[2];
int main() {
void *p = malloc(1337);
- fprintf(stderr, "Test alloc: %p.\n", p);
+ print_address("Test alloc: ", 1, p);
char *char_arr = (char *)arr;
memcpy(char_arr + 1, &p, sizeof(p));
return 0;
}
-// CHECK: Test alloc: [[ADDR:.*]].
+// CHECK: Test alloc: [[ADDR:0x[0-9,a-f]+]]
// CHECK: LeakSanitizer: detected memory leaks
// CHECK: [[ADDR]] (1337 bytes)
// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer:
diff --git a/test/lsan/lit.common.cfg b/test/lsan/lit.common.cfg
index a04c113269f29..6002e2d694442 100644
--- a/test/lsan/lit.common.cfg
+++ b/test/lsan/lit.common.cfg
@@ -31,8 +31,9 @@ config.name += config.name_suffix
clang_cflags = ["-O0", config.target_cflags] + config.debug_info_flags
clang_cxxflags = config.cxx_mode_flags + clang_cflags
-clang_lsan_cflags = clang_cflags + lsan_cflags
-clang_lsan_cxxflags = clang_cxxflags + lsan_cflags
+lsan_incdir = config.test_source_root + "/../"
+clang_lsan_cflags = clang_cflags + lsan_cflags + ["-I%s" % lsan_incdir]
+clang_lsan_cxxflags = clang_cxxflags + lsan_cflags + ["-I%s" % lsan_incdir]
config.clang_cflags = clang_cflags
config.clang_cxxflags = clang_cxxflags
diff --git a/test/msan/CMakeLists.txt b/test/msan/CMakeLists.txt
index 176fb4ae1846b..171bcb9618ffe 100644
--- a/test/msan/CMakeLists.txt
+++ b/test/msan/CMakeLists.txt
@@ -10,16 +10,7 @@ endif()
foreach(arch ${MSAN_TEST_ARCH})
set(MSAN_TEST_TARGET_ARCH ${arch})
string(TOLOWER "-${arch}" MSAN_TEST_CONFIG_SUFFIX)
- if(ANDROID OR ${arch} MATCHES "arm|aarch64")
- # This is only true if we are cross-compiling.
- # Build all tests with host compiler and use host tools.
- set(MSAN_TEST_TARGET_CC ${COMPILER_RT_TEST_COMPILER})
- set(MSAN_TEST_TARGET_CFLAGS ${COMPILER_RT_TEST_COMPILER_CFLAGS})
- else()
- get_target_flags_for_arch(${arch} MSAN_TEST_TARGET_CFLAGS)
- string(REPLACE ";" " " MSAN_TEST_TARGET_CFLAGS "${MSAN_TEST_TARGET_CFLAGS}")
- endif()
-
+ get_test_cc_for_arch(${arch} MSAN_TEST_TARGET_CC MSAN_TEST_TARGET_CFLAGS)
string(TOUPPER ${arch} ARCH_UPPER_CASE)
set(CONFIG_NAME ${ARCH_UPPER_CASE}Config)
diff --git a/test/msan/Linux/forkpty.cc b/test/msan/Linux/forkpty.cc
index ae5c7d96ca8a3..c9f04376fd743 100644
--- a/test/msan/Linux/forkpty.cc
+++ b/test/msan/Linux/forkpty.cc
@@ -1,6 +1,9 @@
// RUN: %clangxx_msan -O0 -g %s -lutil -o %t && %run %t
+
#include <assert.h>
#include <pty.h>
+#include <unistd.h>
+#include <cstring>
#include <sanitizer/msan_interface.h>
@@ -12,6 +15,10 @@ main (int argc, char** argv)
assert(__msan_test_shadow(&master, sizeof(master)) == -1);
assert(__msan_test_shadow(&slave, sizeof(slave)) == -1);
+ char ttyname[255];
+ ttyname_r(master, ttyname, sizeof(ttyname));
+ assert(__msan_test_shadow(ttyname, strlen(ttyname) + 1) == -1);
+
int master2;
forkpty(&master2, NULL, NULL, NULL);
assert(__msan_test_shadow(&master2, sizeof(master2)) == -1);
diff --git a/test/msan/Linux/obstack.cc b/test/msan/Linux/obstack.cc
index f1f53be4c9b2c..0a81d8704f1e8 100644
--- a/test/msan/Linux/obstack.cc
+++ b/test/msan/Linux/obstack.cc
@@ -1,5 +1,5 @@
// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -O0 -g -DPOSITIVE %s -o %t && not %run %t |& FileCheck %s
+// RUN: %clangxx_msan -O0 -g -DPOSITIVE %s -o %t && not %run %t 2>&1 | FileCheck %s
#include <obstack.h>
#include <sanitizer/msan_interface.h>
@@ -30,7 +30,7 @@ int main(void) {
__msan_check_mem_is_initialized(p, sizeof(data) + 1);
}
// CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value
- // CHECK: #0 0x{{.*}} in main{{.*}}obstack.cc:[[@LINE-30]]
+ // CHECK: #0 0x{{.*}} in main{{.*}}obstack.cc:[[@LINE-3]]
#endif
}
obstack_free(&obs, 0);
diff --git a/test/msan/Linux/process_vm_readv.cc b/test/msan/Linux/process_vm_readv.cc
index b61578d1bfdad..0a0e0274b8a5c 100644
--- a/test/msan/Linux/process_vm_readv.cc
+++ b/test/msan/Linux/process_vm_readv.cc
@@ -1,5 +1,5 @@
// RUN: %clangxx_msan -std=c++11 -O0 %s -o %t && %run %t
-// RUN: %clangxx_msan -std=c++11 -O0 %s -o %t -DPOSITIVE && not %run %t |& FileCheck %s
+// RUN: %clangxx_msan -std=c++11 -O0 %s -o %t -DPOSITIVE && not %run %t 2>&1 | FileCheck %s
#include <assert.h>
#include <dlfcn.h>
diff --git a/test/msan/Linux/syscalls_sigaction.cc b/test/msan/Linux/syscalls_sigaction.cc
index 1297fae13d122..975ca2ba68772 100644
--- a/test/msan/Linux/syscalls_sigaction.cc
+++ b/test/msan/Linux/syscalls_sigaction.cc
@@ -11,7 +11,11 @@
#include <sanitizer/msan_interface.h>
struct my_kernel_sigaction {
+#if defined(__mips__)
+ long flags, handler;
+#else
long handler, flags, restorer;
+#endif
uint64_t mask[20]; // larger than any known platform
};
@@ -35,6 +39,10 @@ int main() {
memset(&act, 0, sizeof(act));
__msan_poison(&oldact, sizeof(oldact));
__sanitizer_syscall_post_rt_sigaction(0, SIGUSR1, &act, &oldact, 5);
+#if defined(__mips__)
+ assert(__msan_test_shadow(&oldact, sizeof(oldact)) == sizeof(long)*2 + 5);
+#else
assert(__msan_test_shadow(&oldact, sizeof(oldact)) == sizeof(long)*3 + 5);
#endif
+#endif
}
diff --git a/test/msan/allocator_mapping.cc b/test/msan/allocator_mapping.cc
index f47d9a63e09f8..533128f9a0f41 100644
--- a/test/msan/allocator_mapping.cc
+++ b/test/msan/allocator_mapping.cc
@@ -8,7 +8,7 @@
// This test only makes sense for the 64-bit allocator. The 32-bit allocator
// does not have a fixed mapping. Exclude platforms that use the 32-bit
// allocator.
-// UNSUPPORTED: mips64,aarch64
+// UNSUPPORTED: target-is-mips64,target-is-mips64el,aarch64
#include <assert.h>
#include <stdio.h>
diff --git a/test/msan/backtrace.cc b/test/msan/backtrace.cc
index 9cb883c5cf7d0..cde4e8fc1c9eb 100644
--- a/test/msan/backtrace.cc
+++ b/test/msan/backtrace.cc
@@ -15,7 +15,7 @@ void f() {
if (!buf[i])
exit(1);
char **s = backtrace_symbols(buf, sz);
- assert(s > 0);
+ assert(s != 0);
for (int i = 0; i < sz; ++i)
printf("%d\n", (int)strlen(s[i]));
}
diff --git a/test/msan/chained_origin.cc b/test/msan/chained_origin.cc
index ae72c10b6ac8d..7cab15284d2bc 100644
--- a/test/msan/chained_origin.cc
+++ b/test/msan/chained_origin.cc
@@ -1,21 +1,20 @@
// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O3 %s -o %t && \
// RUN: not %run %t >%t.out 2>&1
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-STACK < %t.out
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%short-stack --check-prefix=CHECK-STACK < %t.out
// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -DHEAP=1 -O3 %s -o %t && \
// RUN: not %run %t >%t.out 2>&1
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-HEAP < %t.out
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%short-stack --check-prefix=CHECK-HEAP < %t.out
// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -O3 %s -o %t && \
// RUN: not %run %t >%t.out 2>&1
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-STACK < %t.out
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%short-stack --check-prefix=CHECK-STACK < %t.out
// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -DHEAP=1 -O3 %s -o %t && \
// RUN: not %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-HEAP < %t.out
-
#include <stdio.h>
volatile int x, y;
@@ -48,19 +47,21 @@ int main(int argc, char *argv[]) {
}
// CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value
-// CHECK: {{#0 .* in main.*chained_origin.cc:47}}
+// CHECK: {{#0 .* in main.*chained_origin.cc:}}[[@LINE-4]]
// CHECK: Uninitialized value was stored to memory at
-// CHECK: {{#0 .* in fn_h.*chained_origin.cc:35}}
-// CHECK: {{#1 .* in main.*chained_origin.cc:46}}
+// CHECK-FULL-STACK: {{#0 .* in fn_h.*chained_origin.cc:}}[[@LINE-19]]
+// CHECK-FULL-STACK: {{#1 .* in main.*chained_origin.cc:}}[[@LINE-9]]
+// CHECK-SHORT-STACK: {{#0 .* in fn_h.*chained_origin.cc:}}[[@LINE-21]]
// CHECK: Uninitialized value was stored to memory at
-// CHECK: {{#0 .* in fn_g.*chained_origin.cc:25}}
-// CHECK: {{#1 .* in fn_f.*chained_origin.cc:30}}
-// CHECK: {{#2 .* in main.*chained_origin.cc:45}}
+// CHECK-FULL-STACK: {{#0 .* in fn_g.*chained_origin.cc:}}[[@LINE-34]]
+// CHECK-FULL-STACK: {{#1 .* in fn_f.*chained_origin.cc:}}[[@LINE-30]]
+// CHECK-FULL-STACK: {{#2 .* in main.*chained_origin.cc:}}[[@LINE-16]]
+// CHECK-SHORT-STACK: {{#0 .* in fn_g.*chained_origin.cc:}}[[@LINE-37]]
// CHECK-STACK: Uninitialized value was created by an allocation of 'z' in the stack frame of function 'main'
-// CHECK-STACK: {{#0 .* in main.*chained_origin.cc:38}}
+// CHECK-STACK: {{#0 .* in main.*chained_origin.cc:}}[[@LINE-27]]
// CHECK-HEAP: Uninitialized value was created by a heap allocation
-// CHECK-HEAP: {{#1 .* in main.*chained_origin.cc:40}}
+// CHECK-HEAP: {{#1 .* in main.*chained_origin.cc:}}[[@LINE-28]]
diff --git a/test/msan/chained_origin_limits.cc b/test/msan/chained_origin_limits.cc
index 90fd09a86b292..9585889eb37a9 100644
--- a/test/msan/chained_origin_limits.cc
+++ b/test/msan/chained_origin_limits.cc
@@ -10,7 +10,7 @@
// RUN: FileCheck %s --check-prefix=CHECK2 < %t.out
// RUN: MSAN_OPTIONS=origin_history_per_stack_limit=1 not %run %t >%t.out 2>&1
-// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK < %t.out
+// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK --check-prefix=CHECK-%short-stack < %t.out
// RUN: MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
@@ -25,7 +25,7 @@
// RUN: FileCheck %s --check-prefix=CHECK2 < %t.out
// RUN: MSAN_OPTIONS=origin_history_per_stack_limit=1 not %run %t >%t.out 2>&1
-// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK < %t.out
+// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK --check-prefix=CHECK-%short-stack < %t.out
// RUN: MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
@@ -41,7 +41,7 @@
// RUN: FileCheck %s --check-prefix=CHECK2 < %t.out
// RUN: MSAN_OPTIONS=origin_history_per_stack_limit=1 not %run %t >%t.out 2>&1
-// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK < %t.out
+// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK --check-prefix=CHECK-%short-stack < %t.out
// RUN: MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
@@ -57,7 +57,7 @@
// RUN: FileCheck %s --check-prefix=CHECK2 < %t.out
// RUN: MSAN_OPTIONS=origin_history_per_stack_limit=1 not %run %t >%t.out 2>&1
-// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK < %t.out
+// RUN: FileCheck %s --check-prefix=CHECK-PER-STACK --check-prefix=CHECK-%short-stack < %t.out
// RUN: MSAN_OPTIONS=origin_history_size=7,origin_history_per_stack_limit=0 not %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
@@ -147,13 +147,21 @@ int main(void) {
// CHECK2-NOT: Uninitialized value was stored to memory at
// CHECK2: Uninitialized value was created
+// For architectures with short stack all the stacks in the chain are same
+// because the stack trace does not contain frames upto the functions fn1, fn2,
+// fn3 from where the uninitialized stores actually originate. Since we report
+// uninitialized value store once for each stack frame
+// (origin_history_per_stack_limit = 1) we expect only one instance of
+// "Uninitialized value was stored to memory at".
+
// CHECK-PER-STACK: WARNING: MemorySanitizer: use-of-uninitialized-value
// CHECK-PER-STACK: Uninitialized value was stored to memory at
-// CHECK-PER-STACK: in fn3
-// CHECK-PER-STACK: Uninitialized value was stored to memory at
-// CHECK-PER-STACK: in fn2
-// CHECK-PER-STACK: Uninitialized value was stored to memory at
-// CHECK-PER-STACK: in fn1
+// CHECK-SHORT-STACK: in __msan_memmove
+// CHECK-FULL-STACK: in fn3
+// CHECK-FULL-STACK: Uninitialized value was stored to memory at
+// CHECK-FULL-STACK: in fn2
+// CHECK-FULL-STACK: Uninitialized value was stored to memory at
+// CHECK-FULL-STACK: in fn1
// CHECK-PER-STACK: Uninitialized value was created
// CHECK-UNLIMITED: WARNING: MemorySanitizer: use-of-uninitialized-value
diff --git a/test/msan/chained_origin_memcpy.cc b/test/msan/chained_origin_memcpy.cc
index 3fe0b77a06140..bfe50dfec3f51 100644
--- a/test/msan/chained_origin_memcpy.cc
+++ b/test/msan/chained_origin_memcpy.cc
@@ -1,20 +1,19 @@
// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -DOFFSET=0 -O3 %s -o %t && \
// RUN: not %run %t >%t.out 2>&1
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z1 < %t.out
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z1 --check-prefix=CHECK-%short-stack < %t.out
// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -DOFFSET=10 -O3 %s -o %t && \
// RUN: not %run %t >%t.out 2>&1
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z2 < %t.out
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z2 --check-prefix=CHECK-%short-stack < %t.out
// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -DOFFSET=0 -O3 %s -o %t && \
// RUN: not %run %t >%t.out 2>&1
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z1 < %t.out
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z1 --check-prefix=CHECK-%short-stack < %t.out
// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -DOFFSET=10 -O3 %s -o %t && \
// RUN: not %run %t >%t.out 2>&1
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z2 < %t.out
-
+// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-Z2 --check-prefix=CHECK-%short-stack < %t.out
#include <stdio.h>
#include <string.h>
@@ -47,15 +46,17 @@ int main(int argc, char *argv[]) {
}
// CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value
-// CHECK: {{#0 .* in main .*chained_origin_memcpy.cc:46}}
+// CHECK: {{#0 .* in main .*chained_origin_memcpy.cc:}}[[@LINE-4]]
// CHECK: Uninitialized value was stored to memory at
-// CHECK: {{#1 .* in fn_h.*chained_origin_memcpy.cc:38}}
+// CHECK-FULL-STACK: {{#1 .* in fn_h.*chained_origin_memcpy.cc:}}[[@LINE-15]]
+// CHECK-SHORT-STACK: {{#0 .* in __msan_memcpy .*msan_interceptors.cc:}}
// CHECK: Uninitialized value was stored to memory at
-// CHECK: {{#0 .* in fn_g.*chained_origin_memcpy.cc:28}}
-// CHECK: {{#1 .* in fn_f.*chained_origin_memcpy.cc:33}}
+// CHECK-FULL-STACK: {{#0 .* in fn_g.*chained_origin_memcpy.cc:}}[[@LINE-29]]
+// CHECK-FULL-STACK: {{#1 .* in fn_f.*chained_origin_memcpy.cc:}}[[@LINE-25]]
+// CHECK-SHORT-STACK: {{#0 .* in fn_g.*chained_origin_memcpy.cc:}}[[@LINE-31]]
// CHECK-Z1: Uninitialized value was created by an allocation of 'z1' in the stack frame of function 'main'
// CHECK-Z2: Uninitialized value was created by an allocation of 'z2' in the stack frame of function 'main'
-// CHECK: {{#0 .* in main.*chained_origin_memcpy.cc:41}}
+// CHECK: {{#0 .* in main.*chained_origin_memcpy.cc:}}[[@LINE-22]]
diff --git a/test/msan/coverage-levels.cc b/test/msan/coverage-levels.cc
index 710a69aff53a4..b881cecac7e91 100644
--- a/test/msan/coverage-levels.cc
+++ b/test/msan/coverage-levels.cc
@@ -9,7 +9,7 @@
// RUN: MSAN_OPTIONS=coverage=1:verbosity=1:coverage_dir=%T/coverage-levels not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2 --check-prefix=CHECK_WARN
// RUN: %clangxx_msan -O1 -fsanitize-coverage=edge %s -o %t
// RUN: MSAN_OPTIONS=coverage=1:verbosity=1:coverage_dir=%T/coverage-levels not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 --check-prefix=CHECK_WARN
-//
+
volatile int sink;
int main(int argc, char **argv) {
int var;
diff --git a/test/msan/fork.cc b/test/msan/fork.cc
index 78a62d549ec3c..e4dc5490887c7 100644
--- a/test/msan/fork.cc
+++ b/test/msan/fork.cc
@@ -3,13 +3,16 @@
// and verify that origin reads do not deadlock in the child process.
// RUN: %clangxx_msan -std=c++11 -fsanitize-memory-track-origins=2 -g -O3 %s -o %t
-// RUN: MSAN_OPTIONS=store_context_size=1000,origin_history_size=0,origin_history_per_stack_limit=0 %run %t |& FileCheck %s
+// RUN: MSAN_OPTIONS=store_context_size=1000,origin_history_size=0,origin_history_per_stack_limit=0 %run %t 2>&1 | FileCheck %s
// Fun fact: if test output is redirected to a file (as opposed to
// being piped directly to FileCheck), we may lose some "done"s due to
// a kernel bug:
// https://lkml.org/lkml/2014/2/17/324
+// Flaky on PPC64.
+// UNSUPPORTED: powerpc64-target-arch
+// UNSUPPORTED: powerpc64le-target-arch
#include <pthread.h>
#include <unistd.h>
@@ -89,7 +92,7 @@ int main() {
exit(0);
}
}
-
+
for (int i = 0; i < kChildren; ++i) {
pid_t p;
while ((p = wait(NULL)) == -1) { }
diff --git a/test/msan/getutent.cc b/test/msan/getutent.cc
new file mode 100644
index 0000000000000..36f9e1f1f7e30
--- /dev/null
+++ b/test/msan/getutent.cc
@@ -0,0 +1,17 @@
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+
+#include <utmp.h>
+#include <utmpx.h>
+#include <sanitizer/msan_interface.h>
+
+int main(void) {
+ setutent();
+ while (struct utmp *ut = getutent())
+ __msan_check_mem_is_initialized(ut, sizeof(*ut));
+ endutent();
+
+ setutxent();
+ while (struct utmpx *utx = getutxent())
+ __msan_check_mem_is_initialized(utx, sizeof(*utx));
+ endutxent();
+}
diff --git a/test/msan/iconv.cc b/test/msan/iconv.cc
index c2da938169b3a..e5fbbf9241e78 100644
--- a/test/msan/iconv.cc
+++ b/test/msan/iconv.cc
@@ -1,5 +1,5 @@
// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -O0 -g -DPOSITIVE %s -o %t && not %run %t |& FileCheck %s
+// RUN: %clangxx_msan -O0 -g -DPOSITIVE %s -o %t && not %run %t 2>&1 | FileCheck %s
#include <assert.h>
#include <iconv.h>
diff --git a/test/msan/lit.cfg b/test/msan/lit.cfg
index d23ff31bc7483..eb0ed43897caf 100644
--- a/test/msan/lit.cfg
+++ b/test/msan/lit.cfg
@@ -35,3 +35,11 @@ if config.host_os not in ['Linux']:
if config.target_arch != 'aarch64':
config.available_features.add('stable-runtime')
+
+# For mips64, mips64el we have forced store_context_size to 1 because these
+# archs use slow unwinder which is not async signal safe. Therefore we only
+# check the first frame since store_context size is 1.
+if config.host_arch in ['mips64', 'mips64el']:
+ config.substitutions.append( ('CHECK-%short-stack', 'CHECK-SHORT-STACK'))
+else:
+ config.substitutions.append( ('CHECK-%short-stack', 'CHECK-FULL-STACK'))
diff --git a/test/msan/mmap.cc b/test/msan/mmap.cc
index 27a8bb2d6eb5c..65d8beeefe3a7 100644
--- a/test/msan/mmap.cc
+++ b/test/msan/mmap.cc
@@ -19,7 +19,9 @@ bool AddrIsApp(void *p) {
(addr >= 0x510000000000ULL && addr < 0x600000000000ULL) ||
(addr >= 0x700000000000ULL && addr < 0x800000000000ULL);
#elif defined(__mips64)
- return addr >= 0x00e000000000ULL;
+ return (addr >= 0x0000000000ULL && addr <= 0x0200000000ULL) ||
+ (addr >= 0xa200000000ULL && addr <= 0xc000000000ULL) ||
+ addr >= 0xe200000000ULL;
#elif defined(__powerpc64__)
return addr < 0x000100000000ULL || addr >= 0x300000000000ULL;
#elif defined(__aarch64__)
@@ -37,6 +39,12 @@ bool AddrIsApp(void *p) {
{0x2E000000000ULL, 0x2F000000000ULL},
{0x3B000000000ULL, 0x3C000000000ULL},
{0x3F000000000ULL, 0x40000000000ULL},
+ {0x0041000000000ULL, 0x0042000000000ULL},
+ {0x0050000000000ULL, 0x0051000000000ULL},
+ {0x0058000000000ULL, 0x0059000000000ULL},
+ {0x0061000000000ULL, 0x0062000000000ULL},
+ {0x0AAAAA0000000ULL, 0x0AAAB00000000ULL},
+ {0x0FFFF00000000ULL, 0x1000000000000ULL},
};
const size_t mappingsSize = sizeof (mappings) / sizeof (mappings[0]);
diff --git a/test/msan/msan_check_mem_is_initialized.cc b/test/msan/msan_check_mem_is_initialized.cc
index 599cf2d7dd463..2991501921e91 100644
--- a/test/msan/msan_check_mem_is_initialized.cc
+++ b/test/msan/msan_check_mem_is_initialized.cc
@@ -1,5 +1,5 @@
// RUN: %clangxx_msan -O0 -g -DPOSITIVE %s -o %t
-// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK
+// RUN: not %run %t 2>&1 | FileCheck %s
// RUN: MSAN_OPTIONS=verbosity=1 not %run %t 2>&1 | \
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VERBOSE
diff --git a/test/msan/msan_copy_shadow.cc b/test/msan/msan_copy_shadow.cc
index a1c6347ff4e3c..19da73810509c 100644
--- a/test/msan/msan_copy_shadow.cc
+++ b/test/msan/msan_copy_shadow.cc
@@ -1,7 +1,7 @@
// Test that __msan_copy_shadow copies shadow, updates origin and does not touch
// the application memory.
// RUN: %clangxx_msan -fsanitize-memory-track-origins=0 -O0 %s -o %t && not %run %t 2>&1
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 %s -o %t && not %run %t 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-%short-stack %s
#include <assert.h>
#include <string.h>
@@ -28,7 +28,8 @@ int main() {
// CHECK: use-of-uninitialized-value
// CHECK: {{in main.*msan_copy_shadow.cc:}}[[@LINE-2]]
// CHECK: Uninitialized value was stored to memory at
- // CHECK: {{in main.*msan_copy_shadow.cc:}}[[@LINE-8]]
+ // CHECK-FULL-STACK: {{in main.*msan_copy_shadow.cc:}}[[@LINE-8]]
+ // CHECK-SHORT-STACK: {{in __msan_copy_shadow .*msan_interceptors.cc:}}
// CHECK: Uninitialized value was created by a heap allocation
- // CHECK: {{in main.*msan_copy_shadow.cc:}}[[@LINE-22]]
+ // CHECK: {{in main.*msan_copy_shadow.cc:}}[[@LINE-23]]
}
diff --git a/test/msan/print_stats.cc b/test/msan/print_stats.cc
index 39af504179d60..5b46d4ebbff24 100644
--- a/test/msan/print_stats.cc
+++ b/test/msan/print_stats.cc
@@ -1,22 +1,22 @@
// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -g %s -o %t
// RUN: %run %t 2>&1 | \
-// RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NOSTATS %s
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-NOSTATS %s
// RUN: MSAN_OPTIONS=print_stats=1 %run %t 2>&1 | \
-// RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NOSTATS %s
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-NOSTATS %s
// RUN: MSAN_OPTIONS=print_stats=1,atexit=1 %run %t 2>&1 | \
-// RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-STATS %s
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-STATS %s
// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -g -DPOSITIVE=1 %s -o %t
// RUN: not %run %t 2>&1 | \
-// RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NOSTATS %s
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-NOSTATS %s
// RUN: MSAN_OPTIONS=print_stats=1 not %run %t 2>&1 | \
-// RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-STATS %s
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-STATS %s
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -g -DPOSITIVE=1 -mllvm -msan-keep-going=1 %s -o %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -fsanitize-recover=memory -g -DPOSITIVE=1 %s -o %t
// RUN: not %run %t 2>&1 | \
-// RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-NOSTATS --check-prefix=CHECK-KEEPGOING %s
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-NOSTATS,CHECK-RECOVER %s
// RUN: MSAN_OPTIONS=print_stats=1 not %run %t 2>&1 | \
-// RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-STATS --check-prefix=CHECK-KEEPGOING %s
+// RUN: FileCheck --check-prefixes=CHECK,CHECK-STATS,CHECK-RECOVER %s
#include <stdio.h>
int main(int argc, char **argv) {
@@ -42,4 +42,4 @@ int main(int argc, char **argv) {
// CHECK-NOSTATS-NOT: Unique origin histories:
// CHECK-NOSTATS-NOT: History depot allocated bytes:
-// CHECK-KEEPGOING: MemorySanitizer: 1 warnings reported.
+// CHECK-RECOVER: MemorySanitizer: 1 warnings reported.
diff --git a/test/msan/realloc-large-origin.cc b/test/msan/realloc-large-origin.cc
index ce25ad8c47fdf..6893c1d17c48e 100644
--- a/test/msan/realloc-large-origin.cc
+++ b/test/msan/realloc-large-origin.cc
@@ -1,7 +1,7 @@
// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 %s -o %t && not %run %t >%t.out 2>&1
-// RUN: FileCheck %s < %t.out
+// RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-%short-stack %s < %t.out
// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O2 %s -o %t && not %run %t >%t.out 2>&1
-// RUN: FileCheck %s < %t.out
+// RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-%short-stack %s < %t.out
// This is a regression test: there used to be broken "stored to memory at"
// stacks with
@@ -21,10 +21,11 @@ int main(int argc, char **argv) {
// CHECK: {{#0 0x.* in main .*realloc-large-origin.cc:}}[[@LINE-3]]
// CHECK: Uninitialized value was stored to memory at
-// CHECK: {{#0 0x.* in .*realloc}}
-// CHECK: {{#1 0x.* in main .*realloc-large-origin.cc:}}[[@LINE-10]]
+// CHECK-FULL-STACK: {{#0 0x.* in .*realloc}}
+// CHECK-FULL-STACK: {{#1 0x.* in main .*realloc-large-origin.cc:}}[[@LINE-10]]
+// CHECK-SHORT-STACK: {{#0 0x.* in .*realloc}}
// CHECK: Uninitialized value was created by a heap allocation
// CHECK: {{#0 0x.* in .*malloc}}
-// CHECK: {{#1 0x.* in main .*realloc-large-origin.cc:}}[[@LINE-15]]
+// CHECK: {{#1 0x.* in main .*realloc-large-origin.cc:}}[[@LINE-16]]
}
diff --git a/test/msan/keep-going-dso.cc b/test/msan/recover-dso.cc
index f32a513ea9e7a..2f4225659dd43 100644
--- a/test/msan/keep-going-dso.cc
+++ b/test/msan/recover-dso.cc
@@ -1,22 +1,28 @@
// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
-// FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
+// FileCheck --check-prefix=CHECK-RECOVER %s <%t.out
// RUN: %clangxx_msan -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
// FileCheck %s <%t.out
// RUN: %clangxx_msan -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
-// FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
+// FileCheck --check-prefix=CHECK-RECOVER %s <%t.out
-// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && not %run %t >%t.out 2>&1
-// FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
-// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
-// FileCheck %s <%t.out
-// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
-// FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
-
-// Test how -mllvm -msan-keep-going and MSAN_OPTIONS=keep_going affect reports
+// Test how -fsanitize-recover=memory and MSAN_OPTIONS=keep_going affect reports
// from interceptors.
-// -mllvm -msan-keep-going provides the default value of keep_going flag, but is
+// -fsanitize-recover=memory provides the default value of keep_going flag, but is
// always overwritten by MSAN_OPTIONS
+// RUN: %clangxx_msan -fsanitize-recover=memory -O0 %s -o %t && not %run %t >%t.out 2>&1
+// FileCheck --check-prefix=CHECK-RECOVER %s <%t.out
+// RUN: %clangxx_msan -fsanitize-recover=memory -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
+// FileCheck %s <%t.out
+// RUN: %clangxx_msan -fsanitize-recover=memory -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
+// FileCheck --check-prefix=CHECK-RECOVER %s <%t.out
+
+// Test how legacy -mllvm -msan-keep-going and MSAN_OPTIONS=keep_going affect
+// reports from interceptors.
+
+// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// FileCheck --check-prefix=CHECK-RECOVER %s <%t.out
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -28,6 +34,6 @@ int main(int argc, char **argv) {
exit(0);
fprintf(stderr, "Done\n");
// CHECK-NOT: Done
- // CHECK-KEEP-GOING: Done
+ // CHECK-RECOVER: Done
return 0;
}
diff --git a/test/msan/keep-going.cc b/test/msan/recover.cc
index 57729756357d6..cb9916ef4755b 100644
--- a/test/msan/keep-going.cc
+++ b/test/msan/recover.cc
@@ -5,20 +5,27 @@
// RUN: %clangxx_msan -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
// FileCheck %s <%t.out
-// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && not %run %t >%t.out 2>&1
-// FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
-// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
+// Test behavior of -fsanitize-recover=memory and MSAN_OPTIONS=keep_going.
+// -fsanitize-recover=memory provides the default value of keep_going flag; value
+// of 1 can be overwritten by MSAN_OPTIONS, value of 0 can not.
+
+// RUN: %clangxx_msan -fsanitize-recover=memory -O0 %s -o %t && not %run %t >%t.out 2>&1
+// FileCheck --check-prefix=CHECK-RECOVER %s <%t.out
+// RUN: %clangxx_msan -fsanitize-recover=memory -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
// FileCheck %s <%t.out
-// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
-// FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
-// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=halt_on_error=1 not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-recover=memory -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
+// FileCheck --check-prefix=CHECK-RECOVER %s <%t.out
+// RUN: %clangxx_msan -fsanitize-recover=memory -O0 %s -o %t && MSAN_OPTIONS=halt_on_error=1 not %run %t >%t.out 2>&1
// FileCheck %s <%t.out
-// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=halt_on_error=0 not %run %t >%t.out 2>&1
-// FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
+// RUN: %clangxx_msan -fsanitize-recover=memory -O0 %s -o %t && MSAN_OPTIONS=halt_on_error=0 not %run %t >%t.out 2>&1
+// FileCheck --check-prefix=CHECK-RECOVER %s <%t.out
-// Test behaviour of -mllvm -msan-keep-going and MSAN_OPTIONS=keep_going.
-// -mllvm -msan-keep-going provides the default value of keep_going flag; value
-// of 1 can be overwritten by MSAN_OPTIONS, value of 0 can not.
+// Basic test of legacy -mllvm -msan-keep-going and MSAN_OPTIONS=keep_going.
+
+// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// FileCheck --check-prefix=CHECK-RECOVER %s <%t.out
+// RUN: %clangxx_msan -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
+// FileCheck %s <%t.out
#include <stdio.h>
#include <stdlib.h>
@@ -29,6 +36,6 @@ int main(int argc, char **argv) {
exit(0);
fprintf(stderr, "Done\n");
// CHECK-NOT: Done
- // CHECK-KEEP-GOING: Done
+ // CHECK-RECOVER: Done
return 0;
}
diff --git a/test/msan/strlen_of_shadow.cc b/test/msan/strlen_of_shadow.cc
index 3066dd5b61ae9..b9cf5f065d2da 100644
--- a/test/msan/strlen_of_shadow.cc
+++ b/test/msan/strlen_of_shadow.cc
@@ -14,7 +14,7 @@ const char *mem_to_shadow(const char *p) {
#if defined(__x86_64__)
return (char *)((uintptr_t)p ^ 0x500000000000ULL);
#elif defined (__mips64)
- return (char *)((uintptr_t)p & ~0x4000000000ULL);
+ return (char *)((uintptr_t)p ^ 0x8000000000ULL);
#elif defined(__powerpc64__)
#define LINEARIZE_MEM(mem) \
(((uintptr_t)(mem) & ~0x200000000000ULL) ^ 0x100000000000ULL)
diff --git a/test/profile/CMakeLists.txt b/test/profile/CMakeLists.txt
index 0eb2b894748c9..5a4cfa1012b08 100644
--- a/test/profile/CMakeLists.txt
+++ b/test/profile/CMakeLists.txt
@@ -14,13 +14,7 @@ endif()
foreach(arch ${PROFILE_TEST_ARCH})
set(PROFILE_TEST_TARGET_ARCH ${arch})
- if(${arch} MATCHES "arm|aarch64")
- # This is only true if we're cross-compiling.
- set(PROFILE_TEST_TARGET_CFLAGS ${COMPILER_RT_TEST_COMPILER_CFLAGS})
- else()
- get_target_flags_for_arch(${arch} PROFILE_TEST_TARGET_CFLAGS)
- string(REPLACE ";" " " PROFILE_TEST_TARGET_CFLAGS "${PROFILE_TEST_TARGET_CFLAGS}")
- endif()
+ get_test_cc_for_arch(${arch} PROFILE_TEST_TARGET_CC PROFILE_TEST_TARGET_CFLAGS)
set(CONFIG_NAME Profile-${arch})
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
diff --git a/test/profile/Inputs/comdat_rename.h b/test/profile/Inputs/comdat_rename.h
new file mode 100644
index 0000000000000..d30628f13b63c
--- /dev/null
+++ b/test/profile/Inputs/comdat_rename.h
@@ -0,0 +1,13 @@
+struct FOO {
+ FOO() : a(0), b(0) {}
+ int callee();
+ __attribute__((noinline)) void caller(int n) {
+ int r = callee();
+ if (r == 0) {
+ a += n;
+ b += 1;
+ }
+ }
+ int a;
+ int volatile b;
+};
diff --git a/test/profile/Inputs/comdat_rename_1.cc b/test/profile/Inputs/comdat_rename_1.cc
new file mode 100644
index 0000000000000..688e305310c52
--- /dev/null
+++ b/test/profile/Inputs/comdat_rename_1.cc
@@ -0,0 +1,33 @@
+#include "comdat_rename.h"
+// callee's out-of-line instance profile data -- it comes
+// from external calls to it from comdat_rename_2.cc.
+// Its inline instance copy's profile data is different and
+// is collected in 'caller''s context.
+int FOO::callee() {
+ // CHECK-LABEL: define {{.*}}callee{{.*}}
+ // CHECK-NOT: br i1 {{.*}}
+ // CHECK: br {{.*}}label{{.*}}, label %[[BB1:.*]], !prof ![[PD1:[0-9]+]]
+ // CHECK: {{.*}}[[BB1]]:
+ if (b != 0)
+ return a / b;
+ if (a != 0)
+ return 10 / a;
+ return 0;
+}
+
+// This is the 'caller''s comdat copy (after renaming) in this module.
+// The profile counters include a copy of counters from 'callee':
+//
+// CHECK-LABEL: define {{.*}}caller{{.*}}
+// CHECK-NOT: br i1 {{.*}}
+// CHECK: br {{.*}}label{{.*}}, label %[[BB2:.*]], !prof ![[PD2:[0-9]+]]
+// CHECK: {{.*}}[[BB2]]:
+// CHECK: br {{.*}}label{{.*}}, label %{{.*}}, !prof !{{.*}}
+// CHECK: br {{.*}}label %[[BB3:.*]], label %{{.*}} !prof ![[PD3:[0-9]+]]
+// CHECK: {{.*}}[[BB3]]:
+//
+// CHECK:![[PD1]] = !{!"branch_weights", i32 0, i32 1}
+// CHECK:![[PD2]] = !{!"branch_weights", i32 1, i32 0}
+// CHECK:![[PD3]] = !{!"branch_weights", i32 {{.*}}, i32 0}
+
+void test(FOO *foo) { foo->caller(10); }
diff --git a/test/profile/Inputs/comdat_rename_2.cc b/test/profile/Inputs/comdat_rename_2.cc
new file mode 100644
index 0000000000000..5cad79c9f9d8b
--- /dev/null
+++ b/test/profile/Inputs/comdat_rename_2.cc
@@ -0,0 +1,18 @@
+#include "comdat_rename.h"
+extern void test(FOO *);
+FOO foo;
+int main() {
+ test(&foo);
+ foo.caller(20);
+ return 0;
+}
+
+// The copy of 'caller' defined in this module -- it has
+// 'callee' call remaining.
+//
+// CHECK-LABEL: define {{.*}}caller{{.*}}
+// CHECK: {{.*}} call {{.*}}
+// CHECK-NOT: br i1 {{.*}}
+// CHECK: br {{.*}}label %[[BB1:.*]], label{{.*}}!prof ![[PD1:[0-9]+]]
+// CHECK: {{.*}}[[BB1]]:
+// CHECK:![[PD1]] = !{!"branch_weights", i32 0, i32 1}
diff --git a/test/profile/Inputs/extern_template.h b/test/profile/Inputs/extern_template.h
index 01c1d1abfff54..aa59f6c1e6006 100644
--- a/test/profile/Inputs/extern_template.h
+++ b/test/profile/Inputs/extern_template.h
@@ -1,10 +1,10 @@
template <typename T> struct Test {
Test() : M(10) {}
- void doIt(int N) { // CHECK: 2| [[@LINE]]| void doIt
- if (N > 10) { // CHECK: 2| [[@LINE]]| if (N > 10) {
- M += 2; // CHECK: 1| [[@LINE]]| M += 2;
- } else // CHECK: 1| [[@LINE]]| } else
- M -= 2; // CHECK: 1| [[@LINE]]| M -= 2;
+ void doIt(int N) { // CHECK: [[@LINE]]| 2| void doIt
+ if (N > 10) { // CHECK: [[@LINE]]| 2| if (N > 10) {
+ M += 2; // CHECK: [[@LINE]]| 1| M += 2;
+ } else // CHECK: [[@LINE]]| 1| } else
+ M -= 2; // CHECK: [[@LINE]]| 1| M -= 2;
}
T M;
};
diff --git a/test/profile/Inputs/instrprof-comdat.h b/test/profile/Inputs/instrprof-comdat.h
index db1a5ba63e589..61e283cc878ed 100644
--- a/test/profile/Inputs/instrprof-comdat.h
+++ b/test/profile/Inputs/instrprof-comdat.h
@@ -12,12 +12,12 @@ private:
T t;
};
-template <class T> T FOO<T>::DoIt(T ti) { // HEADER: 2| [[@LINE]]|template
- for (T I = 0; I < ti; I++) { // HEADER: 22| [[@LINE]]| for (T
- t += I; // HEADER: 20| [[@LINE]]| t += I;
- if (I > ti / 2) // HEADER: 20| [[@LINE]]| if (I > ti
- t -= 1; // HEADER: 8| [[@LINE]]| t -= 1;
- } // HEADER: 10| [[@LINE]]| }
- // HEADER: 1| [[@LINE]]|
- return t; // HEADER: 1| [[@LINE]]| return t;
+template <class T> T FOO<T>::DoIt(T ti) { // HEADER: [[@LINE]]| 2|template
+ for (T I = 0; I < ti; I++) { // HEADER: [[@LINE]]| 22| for (T
+ t += I; // HEADER: [[@LINE]]| 20| t += I;
+ if (I > ti / 2) // HEADER: [[@LINE]]| 20| if (I > ti
+ t -= 1; // HEADER: [[@LINE]]| 8| t -= 1;
+ } // HEADER: [[@LINE]]| 10| }
+ // HEADER: [[@LINE]]| 1|
+ return t; // HEADER: [[@LINE]]| 1| return t;
}
diff --git a/test/profile/Inputs/instrprof-dynamic-a.cpp b/test/profile/Inputs/instrprof-dynamic-a.cpp
index 5faa9c2b2a80f..7468cd4eb04ef 100644
--- a/test/profile/Inputs/instrprof-dynamic-a.cpp
+++ b/test/profile/Inputs/instrprof-dynamic-a.cpp
@@ -1,7 +1,7 @@
#include "instrprof-dynamic-header.h"
-void a() { // COV: 1| [[@LINE]]|void a
- if (true) { // COV: 1| [[@LINE]]| if
- bar<void>(1); // COV: 1| [[@LINE]]| bar
- bar<char>(1); // COV: 1| [[@LINE]]| bar
- } // COV: 1| [[@LINE]]| }
+void a() { // COV: [[@LINE]]| 1|void a
+ if (true) { // COV: [[@LINE]]| 1| if
+ bar<void>(1); // COV: [[@LINE]]| 1| bar
+ bar<char>(1); // COV: [[@LINE]]| 1| bar
+ } // COV: [[@LINE]]| 1| }
}
diff --git a/test/profile/Linux/comdat_rename.test b/test/profile/Linux/comdat_rename.test
new file mode 100644
index 0000000000000..cd5c672de4f25
--- /dev/null
+++ b/test/profile/Linux/comdat_rename.test
@@ -0,0 +1,6 @@
+// RUN: rm -fr %t.prof
+// RUN: %clangxx_pgogen=%t.prof/ -o %t.gen -O2 %S/../Inputs/comdat_rename_1.cc %S/../Inputs/comdat_rename_2.cc
+// RUN: %run %t.gen
+// RUN: llvm-profdata merge -o %t.profdata %t.prof/
+// RUN: %clangxx_profuse=%t.profdata -O2 -emit-llvm -S %S/../Inputs/comdat_rename_1.cc -o - | FileCheck %S/../Inputs/comdat_rename_1.cc
+// RUN: %clangxx_profuse=%t.profdata -O2 -emit-llvm -S %S/../Inputs/comdat_rename_2.cc -o - | FileCheck %S/../Inputs/comdat_rename_2.cc
diff --git a/test/profile/Linux/coverage_ctors.cpp b/test/profile/Linux/coverage_ctors.cpp
index 317dcfe18b501..021d9df5e7347 100644
--- a/test/profile/Linux/coverage_ctors.cpp
+++ b/test/profile/Linux/coverage_ctors.cpp
@@ -15,9 +15,9 @@ struct Base {
};
struct Derived : public Base {
- Derived(const Derived &) = default; // CHECK: 2| [[@LINE]]| Derived(const Derived &) = default;
- Derived(Derived &&) = default; // CHECK: 1| [[@LINE]]| Derived(Derived &&) = default;
- Derived() = default; // CHECK: 1| [[@LINE]]| Derived() = default
+ Derived(const Derived &) = default; // CHECK: [[@LINE]]| 2| Derived(const Derived &) = default;
+ Derived(Derived &&) = default; // CHECK: [[@LINE]]| 1| Derived(Derived &&) = default;
+ Derived() = default; // CHECK: [[@LINE]]| 1| Derived() = default
};
Derived dd;
@@ -27,6 +27,6 @@ int main() {
Derived dd4(static_cast<Derived &&>(dd3));
if (dd.B != 0 || dd2.B != 5 || dd3.B != 10 || dd4.B != 20)
- return 1; // CHECK: 0| [[@LINE]]| return 1;
+ return 1; // CHECK: [[@LINE]]| 0| return 1;
return 0;
}
diff --git a/test/profile/Linux/coverage_dtor.cpp b/test/profile/Linux/coverage_dtor.cpp
index f35eb100fa12c..16415122040c9 100644
--- a/test/profile/Linux/coverage_dtor.cpp
+++ b/test/profile/Linux/coverage_dtor.cpp
@@ -12,7 +12,7 @@ struct Base {
struct Derived : public Base {
Derived(int K) : Base(K) {}
- ~Derived() = default; // CHECK: 2| [[@LINE]]| ~Derived() = default;
+ ~Derived() = default; // CHECK: [[@LINE]]| 2| ~Derived() = default;
};
int main() {
@@ -21,6 +21,6 @@ int main() {
Derived dd2(90);
}
if (g != 0)
- return 1; // CHECK: 0| [[@LINE]]| return 1;
+ return 1; // CHECK: [[@LINE]]| 0| return 1;
return 0;
}
diff --git a/test/profile/Linux/coverage_test.cpp b/test/profile/Linux/coverage_test.cpp
index 9b4ba073cf0a6..db9a14e26e3c8 100644
--- a/test/profile/Linux/coverage_test.cpp
+++ b/test/profile/Linux/coverage_test.cpp
@@ -17,19 +17,19 @@
// RUN: llvm-profdata merge -o %t.pie.profdata %t.pie.profraw
// RUN: llvm-cov show %t.pie -instr-profile %t.pie.profdata -filename-equivalence 2>&1 | FileCheck %s
-void foo(bool cond) { // CHECK: 1| [[@LINE]]|void foo(
- if (cond) { // CHECK: 1| [[@LINE]]| if (cond) {
- } // CHECK: 0| [[@LINE]]| }
-} // CHECK: 1| [[@LINE]]|}
-void bar() { // CHECK: 1| [[@LINE]]|void bar() {
-} // CHECK: 1| [[@LINE]]|}
-void func() { // CHECK: 0| [[@LINE]]|void func(
-} // CHECK: 0| [[@LINE]]|}
-int main() { // CHECK: 1| [[@LINE]]|int main(
- foo(false); // CHECK: 1| [[@LINE]]| foo(
- bar(); // CHECK: 1| [[@LINE]]| bar(
- return 0; // CHECK: 1| [[@LINE]]| return
-} // CHECK: 1| [[@LINE]]|}
+void foo(bool cond) { // CHECK: [[@LINE]]| 1|void foo(
+ if (cond) { // CHECK: [[@LINE]]| 1| if (cond) {
+ } // CHECK: [[@LINE]]| 0| }
+} // CHECK: [[@LINE]]| 1|}
+void bar() { // CHECK: [[@LINE]]| 1|void bar() {
+} // CHECK: [[@LINE]]| 1|}
+void func() { // CHECK: [[@LINE]]| 0|void func(
+} // CHECK: [[@LINE]]| 0|}
+int main() { // CHECK: [[@LINE]]| 1|int main(
+ foo(false); // CHECK: [[@LINE]]| 1| foo(
+ bar(); // CHECK: [[@LINE]]| 1| bar(
+ return 0; // CHECK: [[@LINE]]| 1| return
+} // CHECK: [[@LINE]]| 1|}
// COVMAP: __llvm_covmap {{.*}}
diff --git a/test/profile/Linux/extern_template.test b/test/profile/Linux/extern_template.test
index ada4d230e9bc4..3ce362783199b 100644
--- a/test/profile/Linux/extern_template.test
+++ b/test/profile/Linux/extern_template.test
@@ -1,12 +1,12 @@
// RUN: %clang -O2 -c -o %t.0.o %S/../Inputs/extern_template.cpp
// RUN: %clang_profgen -O2 -c -o %t.o %S/../Inputs/extern_template.cpp
// RUN: %clang_profgen -O2 -fcoverage-mapping %S/../Inputs/extern_template1.cpp %S/../Inputs/extern_template2.cpp %t.o -o %t
-// RUN: env LLVM_PROFILE_FILE=%t.profraw %t
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
// RUN: llvm-profdata show --all-functions %t.profraw | FileCheck %s
// RUN: llvm-profdata merge -o %t.profdata %t.profraw
// RUN: llvm-cov show -instr-profile=%t.profdata %t | FileCheck %S/../Inputs/extern_template.h
// RUN: %clang_profgen -O2 -fcoverage-mapping %S/../Inputs/extern_template1.cpp %S/../Inputs/extern_template2.cpp %t.0.o -o %t.0
-// RUN: env LLVM_PROFILE_FILE=%t.0.profraw %t.0
+// RUN: env LLVM_PROFILE_FILE=%t.0.profraw %run %t.0
// RUN: llvm-profdata show --all-functions %t.0.profraw | FileCheck %s
// RUN: llvm-profdata merge -o %t.0.profdata %t.0.profraw
// RUN: llvm-cov show -instr-profile=%t.0.profdata %t.0 | FileCheck %S/../Inputs/extern_template.h
diff --git a/test/profile/Linux/instrprof-comdat.test b/test/profile/Linux/instrprof-comdat.test
index b933e96b45042..5a11a241ae6f8 100644
--- a/test/profile/Linux/instrprof-comdat.test
+++ b/test/profile/Linux/instrprof-comdat.test
@@ -1,6 +1,6 @@
RUN: mkdir -p %t.d
RUN: %clangxx_profgen -o %t.d/comdat -fcoverage-mapping -fuse-ld=gold %S/../Inputs/instrprof-comdat-1.cpp %S/../Inputs/instrprof-comdat-2.cpp
-RUN: LLVM_PROFILE_FILE=%t-comdat.profraw %t.d/comdat
+RUN: LLVM_PROFILE_FILE=%t-comdat.profraw %run %t.d/comdat
RUN: llvm-profdata merge -o %t.d/comdat.prof %t-comdat.profraw
RUN: llvm-cov show --filename-equivalence --instr-profile=%t.d/comdat.prof %t.d/comdat | FileCheck --check-prefix=HEADER %S/../Inputs/instrprof-comdat.h
diff --git a/test/profile/Linux/instrprof-cs.c b/test/profile/Linux/instrprof-cs.c
new file mode 100644
index 0000000000000..d825525a532db
--- /dev/null
+++ b/test/profile/Linux/instrprof-cs.c
@@ -0,0 +1,35 @@
+// RUN: rm -fr %t.prof
+// RUN: %clang_pgogen=%t.prof/ -o %t.gen.cs -O2 %s
+// RUN: %run %t.gen.cs
+// RUN: llvm-profdata merge -o %t.cs.profdata %t.prof/
+// Check context sensitive profile
+// RUN: %clang_profuse=%t.cs.profdata -O2 -emit-llvm -S %s -o - | FileCheck %s --check-prefix=CS
+//
+// RUN: %clang_profgen=%t.profraw -o %t.gen.cis -O2 %s
+// RUN: %run %t.gen.cis
+// RUN: llvm-profdata merge -o %t.cis.profdata %t.profraw
+// Check context insenstive profile
+// RUN: %clang_profuse=%t.cis.profdata -O2 -emit-llvm -S %s -o - | FileCheck %s --check-prefix=CIS
+int g1 = 1;
+int volatile g2 = 2;
+static void toggle(int t) {
+ if (t & 1)
+ g1 *= t;
+ else
+ g2 *= t;
+}
+
+int main() {
+ int i;
+ // CS: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
+ // CIS: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD:[0-9]+]]
+ toggle(g1);
+ // CS: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD2:[0-9]+]]
+ // CIS: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD:[0-9]+]]
+ toggle(g2);
+ return 0;
+}
+
+// CS: ![[PD1]] = !{!"branch_weights", i32 0, i32 1}
+// CS: ![[PD2]] = !{!"branch_weights", i32 1, i32 0}
+// CIS: ![[PD]] = !{!"branch_weights", i32 2, i32 2}
diff --git a/test/profile/Linux/lit.local.cfg b/test/profile/Linux/lit.local.cfg
index c8c79fc7d8a77..410ffd8c5b056 100644
--- a/test/profile/Linux/lit.local.cfg
+++ b/test/profile/Linux/lit.local.cfg
@@ -21,6 +21,7 @@ def is_gold_linker_available():
return False
clang_cmd = subprocess.Popen([config.clang, '-fuse-ld=gold', '-xc', '-'],
+ universal_newlines = True,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
diff --git a/test/profile/gcc-flag-compatibility.test b/test/profile/gcc-flag-compatibility.test
index b1087615ec514..5b05e769cb145 100644
--- a/test/profile/gcc-flag-compatibility.test
+++ b/test/profile/gcc-flag-compatibility.test
@@ -2,16 +2,16 @@ RUN: rm -rf %t.d
RUN: mkdir -p %t.d
RUN: %clang_profgen_gcc=%t.d/d1/d2 -o %t.d/code %S/Inputs/gcc-flag-compatibility.c
-# Test that the instrumented code writes to %t.d/d1/d2/default.profraw
+# Test that the instrumented code writes to %t.d/d1/d2/
RUN: %run %t.d/code
-RUN: llvm-profdata merge -o %t.profdata %t.d/d1/d2/default.profraw
+RUN: llvm-profdata merge -o %t.profdata %t.d/d1/d2/
# Test that we can override the directory and file name with LLVM_PROFILE_FILE.
RUN: env LLVM_PROFILE_FILE=%t.d/x1/prof.raw %run %t.d/code
-RUN: llvm-profdata merge -o %t.profdata %t.d/x1/prof.raw
+RUN: llvm-profdata merge -o %t.profdata %t.d/x1/
# Test that we can specify a directory with -fprofile-use.
-RUN: llvm-profdata merge -o %t.d/default.profdata %t.d/x1/prof.raw
+RUN: llvm-profdata merge -o %t.d/default.profdata %t.d/x1/
RUN: %clang_profuse_gcc=%t.d -o %t.d/code %S/Inputs/gcc-flag-compatibility.c
# Test that we can specify a file with -fprofile-use.
diff --git a/test/profile/instrprof-basic.c b/test/profile/instrprof-basic.c
index 02549e1506ba1..dd8f3fca3f9c9 100644
--- a/test/profile/instrprof-basic.c
+++ b/test/profile/instrprof-basic.c
@@ -1,21 +1,46 @@
-// REQUIRES: shell
// RUN: %clang_profgen -o %t -O3 %s
// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
// RUN: llvm-profdata merge -o %t.profdata %t.profraw
// RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s --check-prefix=COMMON --check-prefix=ORIG
//
-// RUN: rm -f %t.profraw_e_*
-// RUN: env LLVM_PROFILE_FILE=%t.profraw_e_%1m %run %t
-// RUN: env LLVM_PROFILE_FILE=%t.profraw_e_%1m %run %t
-// RUN: llvm-profdata merge -o %t.em.profdata %t.profraw_e_*
+// RUN: rm -fr %t.dir1
+// RUN: mkdir -p %t.dir1
+// RUN: env LLVM_PROFILE_FILE=%t.dir1/profraw_e_%1m %run %t
+// RUN: env LLVM_PROFILE_FILE=%t.dir1/profraw_e_%1m %run %t
+// RUN: llvm-profdata merge -o %t.em.profdata %t.dir1
// RUN: %clang_profuse=%t.em.profdata -o - -S -emit-llvm %s | FileCheck %s --check-prefix=COMMON --check-prefix=MERGE
//
-// RUN: %clang_profgen=%t.%m.profraw -o %t.merge -O3 %s
-// RUN: rm -f %t.*.profraw*
+// RUN: rm -fr %t.dir2
+// RUN: mkdir -p %t.dir2
+// RUN: %clang_profgen=%t.dir2/%m.profraw -o %t.merge -O3 %s
// RUN: %run %t.merge
// RUN: %run %t.merge
-// RUN: llvm-profdata merge -o %t.m.profdata %t.*.profraw
+// RUN: llvm-profdata merge -o %t.m.profdata %t.dir2/
// RUN: %clang_profuse=%t.m.profdata -o - -S -emit-llvm %s | FileCheck %s --check-prefix=COMMON --check-prefix=MERGE
+//
+// Test that merging is enabled by default with -fprofile-generate=
+// RUN: rm -fr %t.dir3
+// RUN: mkdir -p %t.dir3
+// RUN: %clang_pgogen=%t.dir3/ -o %t.merge3 -O0 %s
+// RUN: %run %t.merge3
+// RUN: %run %t.merge3
+// RUN: %run %t.merge3
+// RUN: %run %t.merge3
+// RUN: llvm-profdata merge -o %t.m3.profdata %t.dir3/
+// RUN: %clang_profuse=%t.m3.profdata -O0 -o - -S -emit-llvm %s | FileCheck %s --check-prefix=COMMON --check-prefix=PGOMERGE
+//
+// Test that merging is enabled by default with -fprofile-generate
+// RUN: rm -fr %t.dir4
+// RUN: mkdir -p %t.dir4
+// RUN: %clang_pgogen -o %t.dir4/merge4 -O0 %s
+// RUN: cd %t.dir4
+// RUN: %run %t.dir4/merge4
+// RUN: %run %t.dir4/merge4
+// RUN: %run %t.dir4/merge4
+// RUN: %run %t.dir4/merge4
+// RUN: rm -f %t.dir4/merge4
+// RUN: llvm-profdata merge -o %t.m4.profdata ./
+// RUN: %clang_profuse=%t.m4.profdata -O0 -o - -S -emit-llvm %s | FileCheck %s --check-prefix=COMMON --check-prefix=PGOMERGE
int begin(int i) {
// COMMON: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
@@ -45,3 +70,5 @@ int main(int argc, const char *argv[]) {
// ORIG: ![[PD2]] = !{!"branch_weights", i32 2, i32 1}
// MERGE: ![[PD1]] = !{!"branch_weights", i32 1, i32 3}
// MERGE: ![[PD2]] = !{!"branch_weights", i32 3, i32 1}
+// PGOMERGE: ![[PD1]] = !{!"branch_weights", i32 0, i32 4}
+// PGOMERGE: ![[PD2]] = !{!"branch_weights", i32 4, i32 0}
diff --git a/test/profile/instrprof-darwin-dead-strip.c b/test/profile/instrprof-darwin-dead-strip.c
new file mode 100644
index 0000000000000..64a4895a9ef92
--- /dev/null
+++ b/test/profile/instrprof-darwin-dead-strip.c
@@ -0,0 +1,60 @@
+// REQUIRES: osx-ld64-live_support
+// REQUIRES: lto
+
+// RUN: %clang_profgen=%t.profraw -fcoverage-mapping -mllvm -enable-name-compression=false -Wl,-dead_strip -o %t %s
+// RUN: %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-profdata show --all-functions %t.profdata | FileCheck %s -check-prefix=PROF
+// RUN: llvm-cov show %t -instr-profile %t.profdata | FileCheck %s -check-prefix=COV
+// RUN: nm %t | FileCheck %s -check-prefix=NM
+// RUN: otool -s __DATA __llvm_prf_names %t | FileCheck %s -check-prefix=PRF_NAMES
+// RUN: otool -s __DATA __llvm_prf_cnts %t | FileCheck %s -check-prefix=PRF_CNTS
+
+// RUN: %clang_lto_profgen=%t.lto.profraw -fcoverage-mapping -mllvm -enable-name-compression=false -Wl,-dead_strip -flto -o %t.lto %s
+// RUN: %run %t.lto
+// RUN: llvm-profdata merge -o %t.lto.profdata %t.lto.profraw
+// RUN: llvm-profdata show --all-functions %t.lto.profdata | FileCheck %s -check-prefix=PROF
+// RUN: llvm-cov show %t.lto -instr-profile %t.lto.profdata | FileCheck %s -check-prefix=COV
+// RUN: nm %t.lto | FileCheck %s -check-prefix=NM
+// RUN: otool -s __DATA __llvm_prf_names %t.lto | FileCheck %s -check-prefix=PRF_NAMES
+// RUN: otool -s __DATA __llvm_prf_cnts %t.lto | FileCheck %s -check-prefix=PRF_CNTS
+
+// Note: We expect foo() and some of the profiling data associated with it to
+// be dead-stripped.
+
+// COV: [[@LINE+1]]{{ *}}|{{ *}}0|void foo()
+void foo() {}
+
+// COV: [[@LINE+1]]{{ *}}|{{ *}}1|int main
+int main() { return 0; }
+
+// NM-NOT: foo
+
+// PROF: Counters:
+// PROF-NEXT: main:
+// PROF-NEXT: Hash:
+// PROF-NEXT: Counters: 1
+// PROF-NEXT: Function count: 1
+// PROF-NEXT: Functions shown: 1
+// PROF-NEXT: Total functions: 1
+// PROF-NEXT: Maximum function count: 1
+// PROF-NEXT: Maximum internal block count: 0
+
+// Note: We don't expect the names of dead-stripped functions to disappear from
+// __llvm_prf_names, because collectPGOFuncNameStrings() glues the names
+// together.
+
+// PRF_NAMES: Contents of (__DATA,__llvm_prf_names) section
+// PRF_NAMES-NEXT: {{.*}} 08 00 66 6f 6f 01 6d 61 69 6e{{ +$}}
+// | | f o o # m a i n
+// | |___________|
+// | |
+// UncompressedLen = 8 |
+// |
+// CompressedLen = 0
+
+// Note: We expect the profile counters for dead-stripped functions to also be
+// dead-stripped.
+
+// PRF_CNTS: Contents of (__DATA,__llvm_prf_cnts) section
+// PRF_CNTS-NEXT: {{.*}} 00 00 00 00 00 00 00 00{{ +$}}
diff --git a/test/profile/instrprof-dump.c b/test/profile/instrprof-dump.c
new file mode 100644
index 0000000000000..93c3c46f69160
--- /dev/null
+++ b/test/profile/instrprof-dump.c
@@ -0,0 +1,62 @@
+/*
+RUN: rm -fr %t.profdir
+RUN: %clang_profgen=%t.profdir/default_%m.profraw -o %t -O2 %s
+RUN: %run %t 2>&1 | FileCheck %s --check-prefix=NO_EXIT_WRITE
+RUN: llvm-profdata merge -o %t.profdata %t.profdir
+RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s --check-prefix=PROF
+
+NO_EXIT_WRITE: Profile data not written to file: already written
+*/
+
+int __llvm_profile_dump(void);
+void __llvm_profile_reset_counters(void);
+int foo(int);
+int bar(int);
+int skip(int);
+
+int main(int argc, const char *argv[]) {
+ int Ret = foo(0); /* region 1 */
+ __llvm_profile_dump();
+
+ /* not profiled -- cleared later. */
+ skip(0); /* skipped region */
+
+ __llvm_profile_reset_counters();
+ Ret += bar(0); /* region 2 */
+ __llvm_profile_dump();
+
+ skip(1);
+
+ __llvm_profile_reset_counters();
+ /* foo's profile will be merged. */
+ foo(1); /* region 3 */
+ __llvm_profile_dump();
+
+ return Ret;
+}
+
+__attribute__((noinline)) int foo(int X) {
+ /* PROF: define {{.*}} @foo({{.*}}!prof ![[ENT:[0-9]+]]
+ PROF: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
+ */
+ return X <= 0 ? -X : X;
+}
+
+__attribute__((noinline)) int skip(int X) {
+ /* PROF: define {{.*}} @skip(
+ PROF: br i1 %{{.*}}, label %{{.*}}, label %{{[^,]+$}}
+ */
+ return X <= 0 ? -X : X;
+}
+
+__attribute__((noinline)) int bar(int X) {
+ /* PROF-LABEL: define {{.*}} @bar(
+ PROF: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD2:[0-9]+]]
+ */
+ return X <= 0 ? -X : X;
+}
+
+/*
+PROF: ![[ENT]] = !{!"function_entry_count", i64 2}
+PROF: ![[PD1]] = !{!"branch_weights", i32 2, i32 2}
+*/
diff --git a/test/profile/instrprof-icall-promo.test b/test/profile/instrprof-icall-promo.test
index 5332ef0e17c9e..d9b16f67782ec 100644
--- a/test/profile/instrprof-icall-promo.test
+++ b/test/profile/instrprof-icall-promo.test
@@ -1,16 +1,16 @@
-RUN: %clangxx_profgen -O2 -Xclang -fprofile-instrument=llvm -c -o %t.1.o %S/Inputs/instrprof-icall-promo_1.cc
-RUN: %clangxx_profgen -O2 -Xclang -fprofile-instrument=llvm -c -o %t.2.o %S/Inputs/instrprof-icall-promo_2.cc
+# IR based instrumentation
+RUN: %clangxx_pgogen -O2 -c -o %t.1.o %S/Inputs/instrprof-icall-promo_1.cc
+RUN: %clangxx_pgogen -O2 -c -o %t.2.o %S/Inputs/instrprof-icall-promo_2.cc
-RUN: %clangxx_profgen -O2 -Xclang -fprofile-instrument=llvm %t.2.o %t.1.o -o %t.gen.1
+RUN: %clangxx_pgogen -O2 %t.2.o %t.1.o -o %t.gen.1
RUN: env LLVM_PROFILE_FILE=%t-icall.profraw %run %t.gen.1
RUN: llvm-profdata merge -o %t-icall.profdata %t-icall.profraw
-RUN: %clangxx -O2 -Rpass=pgo-icall-prom -fprofile-instr-use=%t-icall.profdata -c -o %t.2.use.o %S/Inputs/instrprof-icall-promo_2.cc 2>&1 | FileCheck %s
+RUN: %clangxx_profuse=%t-icall.profdata -O2 -Rpass=pgo-icall-prom -c -o %t.2.use.o %S/Inputs/instrprof-icall-promo_2.cc 2>&1 | FileCheck %s
-RUN: %clangxx_profgen -O2 -Xclang -fprofile-instrument=llvm %t.1.o %t.2.o -o %t.gen.2
+RUN: %clangxx_pgogen -O2 %t.1.o %t.2.o -o %t.gen.2
RUN: env LLVM_PROFILE_FILE=%t-icall2.profraw %run %t.gen.2
RUN: llvm-profdata merge -o %t-icall2.profdata %t-icall2.profraw
-# The following test will be re-enabled once a compiler bug is fixed.
-RUN: %clangxx -O2 -Rpass=pgo-icall-prom -fprofile-instr-use=%t-icall2.profdata -c -o %t.2.use.o %S/Inputs/instrprof-icall-promo_2.cc 2>&1 | FileCheck %s
+RUN: %clangxx_profuse=%t-icall2.profdata -O2 -Rpass=pgo-icall-prom -c -o %t.2.use.o %S/Inputs/instrprof-icall-promo_2.cc 2>&1 | FileCheck %s
# CHECK: Promote indirect call to
diff --git a/test/profile/instrprof-override-filename-then-reset-default.c b/test/profile/instrprof-override-filename-then-reset-default.c
index 137a3b2f22915..3438227213ecd 100644
--- a/test/profile/instrprof-override-filename-then-reset-default.c
+++ b/test/profile/instrprof-override-filename-then-reset-default.c
@@ -7,13 +7,13 @@
// RUN: %clang_profuse=%t.d/default.profdata -o - -S -emit-llvm %s | FileCheck %s
-void __llvm_profile_override_default_filename(const char *);
+void __llvm_profile_set_filename(const char *);
int main(int argc, const char *argv[]) {
// CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
if (argc < 2)
return 1;
- __llvm_profile_override_default_filename(argv[1]);
- __llvm_profile_override_default_filename(0);
+ __llvm_profile_set_filename(argv[1]);
+ __llvm_profile_set_filename(0);
return 0;
}
// CHECK: ![[PD1]] = !{!"branch_weights", i32 1, i32 2}
diff --git a/test/profile/instrprof-override-filename-with-env.c b/test/profile/instrprof-override-filename-with-env.c
index cce83891663a6..3f4e5c8d251c4 100644
--- a/test/profile/instrprof-override-filename-with-env.c
+++ b/test/profile/instrprof-override-filename-with-env.c
@@ -1,14 +1,14 @@
-// RUN: %clang_profgen -o %t -O3 %s
+// RUN: %clang_profgen=%t.bad.profraw -o %t -O3 %s
// RUN: env LLVM_PROFILE_FILE=%t.good.profraw %run %t %t.bad.profraw
// RUN: llvm-profdata merge -o %t.profdata %t.good.profraw
// RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s
-void __llvm_profile_override_default_filename(const char *);
+void bar () {}
int main(int argc, const char *argv[]) {
// CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
if (argc < 2)
return 1;
- __llvm_profile_override_default_filename(argv[1]);
+ bar();
return 0;
}
// CHECK: ![[PD1]] = !{!"branch_weights", i32 1, i32 2}
diff --git a/test/profile/instrprof-override-filename.c b/test/profile/instrprof-override-filename.c
index 59dea29e3b884..a67c7076afb5c 100644
--- a/test/profile/instrprof-override-filename.c
+++ b/test/profile/instrprof-override-filename.c
@@ -1,14 +1,14 @@
-// RUN: %clang_profgen -o %t -O3 %s
+// RUN: %clang_profgen=%t.profraw -o %t -O3 %s
// RUN: %run %t %t.profraw
// RUN: llvm-profdata merge -o %t.profdata %t.profraw
// RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s
-void __llvm_profile_override_default_filename(const char *);
+void bar() {}
int main(int argc, const char *argv[]) {
// CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]]
if (argc < 2)
return 1;
- __llvm_profile_override_default_filename(argv[1]);
+ bar();
return 0;
}
// CHECK: ![[PD1]] = !{!"branch_weights", i32 1, i32 2}
diff --git a/test/profile/instrprof-path.c b/test/profile/instrprof-path.c
new file mode 100644
index 0000000000000..28ee8ad0a4843
--- /dev/null
+++ b/test/profile/instrprof-path.c
@@ -0,0 +1,39 @@
+// RUN: %clang_pgogen -O2 -o %t.0 %s
+// RUN: %clang_pgogen=%t.d1 -O2 -o %t.1 %s
+// RUN: %clang_pgogen=%t.d1/%t.d2 -O2 -o %t.2 %s
+//
+// RUN: %run %t.0 ""
+// RUN: env LLVM_PROFILE_FILE=%t.d1/default.profraw %run %t.0 %t.d1/
+// RUN: env LLVM_PROFILE_FILE=%t.d1/%t.d2/default.profraw %run %t.0 %t.d1/%t.d2/
+// RUN: %run %t.1 %t.d1/
+// RUN: %run %t.2 %t.d1/%t.d2/
+// RUN: %run %t.2 %t.d1/%t.d2/ %t.d1/%t.d2/%t.d3/blah.profraw %t.d1/%t.d2/%t.d3/
+
+#include <string.h>
+
+const char *__llvm_profile_get_path_prefix();
+void __llvm_profile_set_filanem(const char*);
+
+int main(int argc, const char *argv[]) {
+ int i;
+ const char *expected;
+ const char *prefix;
+ if (argc < 2)
+ return 1;
+
+ expected = argv[1];
+ prefix = __llvm_profile_get_path_prefix();
+
+ if (strcmp(prefix, expected))
+ return 1;
+
+ if (argc == 4) {
+ __llvm_profile_set_filename(argv[2]);
+ prefix = __llvm_profile_get_path_prefix();
+ expected = argv[3];
+ if (strcmp(prefix, expected))
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/test/profile/Linux/instrprof-set-filename-shared.test b/test/profile/instrprof-set-filename-shared.test
index 29e6713289d96..afcb4b4fd2d62 100644
--- a/test/profile/Linux/instrprof-set-filename-shared.test
+++ b/test/profile/instrprof-set-filename-shared.test
@@ -1,7 +1,7 @@
# Test that __llvm_profile_set_filename is honored by shared libary too.
RUN: mkdir -p %t.d
-RUN: %clang_profgen=%t.shared.profraw -fPIC -shared -o %t.d/t.shared %S/../Inputs/instrprof-dlopen-func.c
-RUN: %clang_profgen -DCALL_SHARED -o %t.m -O3 -rpath %t.d %t.d/t.shared %S/../instrprof-set-filename.c
+RUN: %clang_profgen=%t.shared.profraw -fPIC -shared -o %t.d/t.shared %S/Inputs/instrprof-dlopen-func.c
+RUN: %clang_profgen -DCALL_SHARED -o %t.m -O3 -rpath %t.d %t.d/t.shared %S/instrprof-set-filename.c
RUN: %run %t.m %t.main.profraw
RUN: llvm-profdata show %t.main.profraw | FileCheck --check-prefix=SHARED %s
diff --git a/test/profile/instrprof-value-prof-evict.test b/test/profile/instrprof-value-prof-evict.test
index de82581e451af..8b054fb24371e 100644
--- a/test/profile/instrprof-value-prof-evict.test
+++ b/test/profile/instrprof-value-prof-evict.test
@@ -4,13 +4,13 @@
// RUN: llvm-profdata show --all-functions -ic-targets %t.profdata | FileCheck %S/Inputs/instrprof-value-prof-evict.c
// IR level instrumentation
-// RUN: %clang_profgen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=10 -Xclang -fprofile-instrument=llvm -o %t.ir %S/Inputs/instrprof-value-prof-evict.c
+// RUN: %clang_pgogen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=10 -o %t.ir %S/Inputs/instrprof-value-prof-evict.c
// RUN: env LLVM_PROFILE_FILE=%t.ir.profraw %run %t.ir
// RUN: llvm-profdata merge -o %t.ir.profdata %t.ir.profraw
// RUN: llvm-profdata show --all-functions -ic-targets %t.ir.profdata | FileCheck %S/Inputs/instrprof-value-prof-evict.c
// IR level instrumentation, dynamic allocation
-// RUN: %clang_profgen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=false -Xclang -fprofile-instrument=llvm -o %t.ir.dyn %S/Inputs/instrprof-value-prof-evict.c
+// RUN: %clang_pgogen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=false -o %t.ir.dyn %S/Inputs/instrprof-value-prof-evict.c
// RUN: env LLVM_PROFILE_FILE=%t.ir.dyn.profraw %run %t.ir.dyn
// RUN: llvm-profdata merge -o %t.ir.dyn.profdata %t.ir.dyn.profraw
// RUN: llvm-profdata show --all-functions -ic-targets %t.ir.dyn.profdata | FileCheck %S/Inputs/instrprof-value-prof-evict.c
diff --git a/test/profile/instrprof-value-prof-reset.c b/test/profile/instrprof-value-prof-reset.c
new file mode 100644
index 0000000000000..b3744f5735066
--- /dev/null
+++ b/test/profile/instrprof-value-prof-reset.c
@@ -0,0 +1,47 @@
+// RUN: %clang_profgen -O2 -mllvm -enable-value-profiling=true -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=3 -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-profdata show --all-functions -ic-targets %t.profdata | FileCheck %s
+
+// IR level instrumentation
+// RUN: %clang_pgogen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=3 -o %t.ir %s
+// RUN: env LLVM_PROFILE_FILE=%t.ir.profraw %run %t.ir
+// RUN: llvm-profdata merge -o %t.ir.profdata %t.ir.profraw
+// RUN: llvm-profdata show --all-functions -ic-targets %t.ir.profdata | FileCheck %s
+
+// IR level instrumentation, dynamic allocation
+// RUN: %clang_pgogen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=false -o %t.ir.dyn %s
+// RUN: env LLVM_PROFILE_FILE=%t.ir.dyn.profraw %run %t.ir.dyn
+// RUN: llvm-profdata merge -o %t.ir.dyn.profdata %t.ir.dyn.profraw
+// RUN: llvm-profdata show --all-functions -ic-targets %t.ir.dyn.profdata | FileCheck %s
+void callee_0() {}
+void callee_1() {}
+void callee_2() {}
+
+void *CalleeAddrs[] = {callee_0, callee_1, callee_2, callee_2, callee_2};
+extern void lprofSetMaxValsPerSite(unsigned);
+extern void __llvm_profile_reset_counters();
+
+typedef void (*FPT)(void);
+
+
+// Testing value profiling eviction algorithm.
+FPT getCalleeFunc(int I) { return CalleeAddrs[I]; }
+
+int main() {
+ int I;
+
+ // First fill up two value profile entries with two targets
+ lprofSetMaxValsPerSite(2);
+
+ for (I = 0; I < 5; I++) {
+ if (I == 2) {
+ __llvm_profile_reset_counters();
+ }
+ // CHECK: callee_2, 3
+ // CHECK-NEXT: callee_1, 0
+ // CHECK-NOT: callee_0,
+ FPT FP = getCalleeFunc(I);
+ FP();
+ }
+}
diff --git a/test/profile/instrprof-value-prof-shared.test b/test/profile/instrprof-value-prof-shared.test
index 5b6d627dbaf93..a45b0d55b2363 100644
--- a/test/profile/instrprof-value-prof-shared.test
+++ b/test/profile/instrprof-value-prof-shared.test
@@ -7,8 +7,9 @@
// RUN: llvm-profdata show --all-functions -ic-targets %t.profdata | FileCheck %S/Inputs/instrprof-value-prof-real.c --check-prefix=SHARED
// IR level instrumentation
-// RUN: %clang_profgen -O2 -mllvm -disable-vp=false -Xclang -fprofile-instrument=llvm -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=256 -fPIC -shared -o %t.d/t.ir.shared -DSHARED_LIB %S/Inputs/instrprof-value-prof-real.c
-// RUN: %clang_profgen -O2 -mllvm -disable-vp=false -Xclang -fprofile-instrument=llvm -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=256 -rpath %t.d -o %t.ir %t.d/t.ir.shared -DCALL_SHARED %S/Inputs/instrprof-value-prof-real.c
+// RUN: %clang_pgogen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=256 -fPIC -shared -o %t.d/t.ir.shared -DSHARED_LIB %S/Inputs/instrprof-value-prof-real.c
+// RUN: %clang_pgogen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=256 -rpath %t.d -o %t.ir %t.d/t.ir.shared -DCALL_SHARED %S/Inputs/instrprof-value-prof-real.c
+// Profile data from shared library will be concatenated to the same raw file.
// RUN: env LLVM_PROFILE_FILE=%t.ir.profraw LLVM_VP_MAX_NUM_VALS_PER_SITE=255 %run %t.ir
// RUN: llvm-profdata merge -o %t.ir.profdata %t.ir.profraw
// RUN: llvm-profdata show --all-functions -ic-targets %t.ir.profdata | FileCheck %S/Inputs/instrprof-value-prof-real.c
@@ -16,9 +17,23 @@
// RUN: llvm-profdata show --all-functions -ic-targets %t.ir.profdata | FileCheck %S/Inputs/instrprof-value-prof-real.c --check-prefix=SHARED
// RUN: FileCheck %S/Inputs/instrprof-value-prof-real.c --check-prefix=IR < %t.ir.proftxt
+// Same as above but with profile online merging enabled.
+// RUN: rm -fr %t.prof/
+// RUN: mkdir -p %t.prof/
+// RUN: %clang_pgogen=%t.prof -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=256 -fPIC -shared -o %t.d/t.ir.m.shared -DSHARED_LIB %S/Inputs/instrprof-value-prof-real.c
+// RUN: %clang_pgogen=%t.prof -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=256 -rpath %t.d -o %t.ir.m %t.d/t.ir.m.shared -DCALL_SHARED %S/Inputs/instrprof-value-prof-real.c
+// RUN: env LLVM_VP_MAX_NUM_VALS_PER_SITE=255 %run %t.ir.m
+// RUN: llvm-profdata merge -o %t.ir.m.profdata -dump-input-file-list %t.prof/ | count 2
+// RUN: llvm-profdata merge -o %t.ir.m.profdata %t.prof/
+// RUN: llvm-profdata show --all-functions -ic-targets %t.ir.m.profdata | FileCheck %S/Inputs/instrprof-value-prof-real.c
+// RUN: llvm-profdata merge -text %t.ir.m.profdata -o %t.ir.m.proftxt
+// RUN: llvm-profdata show --all-functions -ic-targets %t.ir.m.profdata | FileCheck %S/Inputs/instrprof-value-prof-real.c --check-prefix=SHARED
+// RUN: FileCheck %S/Inputs/instrprof-value-prof-real.c --check-prefix=IR < %t.ir.m.proftxt
+
+
// IR level instrumentation: dynamic memory allocation
-// RUN: %clang_profgen -O2 -mllvm -disable-vp=false -Xclang -fprofile-instrument=llvm -mllvm -vp-static-alloc=false -mllvm -vp-counters-per-site=256 -fPIC -shared -o %t.d/t.ir.dyn.shared -DSHARED_LIB %S/Inputs/instrprof-value-prof-real.c
-// RUN: %clang_profgen -O2 -mllvm -disable-vp=false -Xclang -fprofile-instrument=llvm -mllvm -vp-static-alloc=false -mllvm -vp-counters-per-site=256 -rpath %t.d -o %t.ir.dyn %t.d/t.ir.dyn.shared -DCALL_SHARED %S/Inputs/instrprof-value-prof-real.c
+// RUN: %clang_pgogen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=false -mllvm -vp-counters-per-site=256 -fPIC -shared -o %t.d/t.ir.dyn.shared -DSHARED_LIB %S/Inputs/instrprof-value-prof-real.c
+// RUN: %clang_pgogen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=false -mllvm -vp-counters-per-site=256 -rpath %t.d -o %t.ir.dyn %t.d/t.ir.dyn.shared -DCALL_SHARED %S/Inputs/instrprof-value-prof-real.c
// RUN: env LLVM_PROFILE_FILE=%t.ir.dyn.profraw %run %t.ir.dyn
// RUN: llvm-profdata merge -o %t.ir.dyn.profdata %t.ir.dyn.profraw
// RUN: llvm-profdata show --all-functions -ic-targets %t.ir.dyn.profdata | FileCheck %S/Inputs/instrprof-value-prof-real.c
@@ -27,8 +42,8 @@
// RUN: FileCheck %S/Inputs/instrprof-value-prof-real.c --check-prefix=IR < %t.ir.dyn.proftxt
// IR level instrumentation: main program uses static counter, shared library uses dynamic memory alloc.
-// RUN: %clang_profgen -O2 -mllvm -disable-vp=false -Xclang -fprofile-instrument=llvm -mllvm -vp-static-alloc=false -mllvm -vp-counters-per-site=256 -fPIC -shared -o %t.d/t.ir.dyn.shared -DSHARED_LIB %S/Inputs/instrprof-value-prof-real.c
-// RUN: %clang_profgen -O2 -mllvm -disable-vp=false -Xclang -fprofile-instrument=llvm -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=256 -rpath %t.d -o %t.ir.mixed %t.d/t.ir.dyn.shared -DCALL_SHARED %S/Inputs/instrprof-value-prof-real.c
+// RUN: %clang_pgogen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=false -mllvm -vp-counters-per-site=256 -fPIC -shared -o %t.d/t.ir.dyn.shared -DSHARED_LIB %S/Inputs/instrprof-value-prof-real.c
+// RUN: %clang_pgogen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=256 -rpath %t.d -o %t.ir.mixed %t.d/t.ir.dyn.shared -DCALL_SHARED %S/Inputs/instrprof-value-prof-real.c
// RUN: env LLVM_PROFILE_FILE=%t.ir.mixed.profraw LLVM_VP_MAX_NUM_VALS_PER_SITE=255 %run %t.ir.mixed
// RUN: llvm-profdata merge -o %t.ir.mixed.profdata %t.ir.mixed.profraw
// RUN: llvm-profdata show --all-functions -ic-targets %t.ir.mixed.profdata | FileCheck %S/Inputs/instrprof-value-prof-real.c
diff --git a/test/profile/instrprof-value-prof.test b/test/profile/instrprof-value-prof.test
index 8e7f513d20cbf..02038990bfd91 100644
--- a/test/profile/instrprof-value-prof.test
+++ b/test/profile/instrprof-value-prof.test
@@ -4,7 +4,7 @@
// RUN: llvm-profdata show --all-functions -ic-targets %t.profdata | FileCheck %S/Inputs/instrprof-value-prof-real.c
// IR level instrumentation
-// RUN: %clang_profgen -O2 -mllvm -disable-vp=false -Xclang -fprofile-instrument=llvm -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=256 -o %t.ir %S/Inputs/instrprof-value-prof-real.c
+// RUN: %clang_pgogen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=true -mllvm -vp-counters-per-site=256 -o %t.ir %S/Inputs/instrprof-value-prof-real.c
// RUN: env LLVM_PROFILE_FILE=%t.ir.profraw LLVM_VP_MAX_NUM_VALS_PER_SITE=255 %run %t.ir
// RUN: llvm-profdata merge -o %t.ir.profdata %t.ir.profraw
// RUN: llvm-profdata show --all-functions -ic-targets %t.ir.profdata | FileCheck %S/Inputs/instrprof-value-prof-real.c
@@ -12,7 +12,7 @@
// RUN: FileCheck %S/Inputs/instrprof-value-prof-real.c --check-prefix=IR < %t.ir.proftxt
// IR level instrumentation with dynamic memory allocation
-// RUN: %clang_profgen -O2 -mllvm -disable-vp=false -Xclang -fprofile-instrument=llvm -mllvm -vp-static-alloc=false -mllvm -vp-counters-per-site=256 -o %t.ir.dyn %S/Inputs/instrprof-value-prof-real.c
+// RUN: %clang_pgogen -O2 -mllvm -disable-vp=false -mllvm -vp-static-alloc=false -mllvm -vp-counters-per-site=256 -o %t.ir.dyn %S/Inputs/instrprof-value-prof-real.c
// RUN: env LLVM_PROFILE_FILE=%t.ir.dyn.profraw %run %t.ir.dyn
// RUN: llvm-profdata merge -o %t.ir.dyn.profdata %t.ir.dyn.profraw
// RUN: llvm-profdata show --all-functions -ic-targets %t.ir.dyn.profdata | FileCheck %S/Inputs/instrprof-value-prof-real.c
diff --git a/test/profile/instrprof-visibility.cpp b/test/profile/instrprof-visibility.cpp
index 08b886536fb47..6fbba9defc565 100644
--- a/test/profile/instrprof-visibility.cpp
+++ b/test/profile/instrprof-visibility.cpp
@@ -56,34 +56,34 @@ int main() {
// --- Check coverage for functions in the anonymous namespace.
// COV-DAG: instrprof-visibility.cpp:_ZN12_GLOBAL__N_14callEv
-// COV-DAG: 1|{{.*}}|void call() {
-// COV-DAG: 1|{{.*}}| f1();
-// COV-DAG: 1|{{.*}}|#ifndef NO_WEAK
-// COV-DAG: |{{.*}}| f2();
-// COV-DAG: |{{.*}}|#endif
-// COV-DAG: 1|{{.*}}| f3();
-// COV-DAG: 1|{{.*}}|#ifndef NO_EXTERN
-// COV-DAG: |{{.*}}| f4();
-// COV-DAG: |{{.*}}|#endif
-// COV-DAG: 1|{{.*}}| f5();
-// COV-DAG: 1|{{.*}}| f6();
-// COV-DAG: 1|{{.*}}| f7();
-// COV-DAG: 1|{{.*}}|}
+// COV-DAG: [[CALL:[0-9]+]]|{{ *}}1|void call() {
+// COV-DAG: {{.*}}|{{ *}}1| f1();
+// COV-DAG: {{.*}}|{{ *}}1|#ifndef NO_WEAK
+// COV-DAG: {{.*}}|{{ *}} | f2();
+// COV-DAG: {{.*}}|{{ *}} |#endif
+// COV-DAG: {{.*}}|{{ *}}1| f3();
+// COV-DAG: {{.*}}|{{ *}}1|#ifndef NO_EXTERN
+// COV-DAG: {{.*}}|{{ *}} | f4();
+// COV-DAG: {{.*}}|{{ *}} |#endif
+// COV-DAG: {{.*}}|{{ *}}1| f5();
+// COV-DAG: {{.*}}|{{ *}}1| f6();
+// COV-DAG: {{.*}}|{{ *}}1| f7();
+// COV-DAG: {{.*}}|{{ *}}1|}
// --- Check coverage for functions in namespace N1.
// COV-DAG: _ZN2N14callEv
-// COV-DAG: 1|{{.*}}|void call() {
-// COV-DAG: 1|{{.*}}| f1();
-// COV-DAG: 1|{{.*}}|#ifndef NO_WEAK
-// COV-DAG: 1|{{.*}}| f2();
-// COV-DAG: 1|{{.*}}|#endif
-// COV-DAG: 1|{{.*}}| f3();
-// COV-DAG: 1|{{.*}}|#ifndef NO_EXTERN
-// COV-DAG: 1|{{.*}}| f4();
-// COV-DAG: 1|{{.*}}|#endif
-// COV-DAG: 1|{{.*}}| f5();
-// COV-DAG: 1|{{.*}}| f6();
-// COV-DAG: 1|{{.*}}| f7();
-// COV-DAG: 1|{{.*}}|}
+// COV-DAG: {{ *}}[[CALL]]|{{ *}}1|void call() {
+// COV-DAG: {{.*}}|{{ *}}1| f1();
+// COV-DAG: {{.*}}|{{ *}}1|#ifndef NO_WEAK
+// COV-DAG: {{.*}}|{{ *}}1| f2();
+// COV-DAG: {{.*}}|{{ *}}1|#endif
+// COV-DAG: {{.*}}|{{ *}}1| f3();
+// COV-DAG: {{.*}}|{{ *}}1|#ifndef NO_EXTERN
+// COV-DAG: {{.*}}|{{ *}}1| f4();
+// COV-DAG: {{.*}}|{{ *}}1|#endif
+// COV-DAG: {{.*}}|{{ *}}1| f5();
+// COV-DAG: {{.*}}|{{ *}}1| f6();
+// COV-DAG: {{.*}}|{{ *}}1| f7();
+// COV-DAG: {{.*}}|{{ *}}1|}
// COV-DAG: instrprof-visibility.cpp
diff --git a/test/profile/lit.cfg b/test/profile/lit.cfg
index 3512e0abcf1a6..a6e6ef81c6228 100644
--- a/test/profile/lit.cfg
+++ b/test/profile/lit.cfg
@@ -49,20 +49,35 @@ target_cflags=[get_required_attr(config, "target_cflags")]
clang_cflags = target_cflags + extra_linkflags
clang_cxxflags = config.cxx_mode_flags + clang_cflags
-def build_invocation(compile_flags):
- return " " + " ".join([config.clang] + compile_flags) + " "
+def build_invocation(compile_flags, with_lto = False):
+ lto_flags = []
+ lto_prefix = []
+ if with_lto and config.lto_supported:
+ lto_flags += config.lto_flags
+ lto_prefix += config.lto_launch
+ return " " + " ".join(lto_prefix + [config.clang] + lto_flags + compile_flags) + " "
# Add clang substitutions.
config.substitutions.append( ("%clang ", build_invocation(clang_cflags)) )
config.substitutions.append( ("%clangxx ", build_invocation(clang_cxxflags)) )
config.substitutions.append( ("%clang_profgen ", build_invocation(clang_cflags) + " -fprofile-instr-generate ") )
config.substitutions.append( ("%clang_profgen=", build_invocation(clang_cflags) + " -fprofile-instr-generate=") )
-config.substitutions.append( ("%clang_profuse=", build_invocation(clang_cflags) + " -fprofile-instr-use=") )
+config.substitutions.append( ("%clang_pgogen ", build_invocation(clang_cflags) + " -fprofile-generate ") )
+config.substitutions.append( ("%clang_pgogen=", build_invocation(clang_cflags) + " -fprofile-generate=") )
+
config.substitutions.append( ("%clangxx_profgen ", build_invocation(clang_cxxflags) + " -fprofile-instr-generate ") )
-config.substitutions.append( ("%clangxx_profuse=", build_invocation(clang_cxxflags) + " -fprofile-instr-use=") )
+config.substitutions.append( ("%clangxx_profgen=", build_invocation(clang_cxxflags) + " -fprofile-instr-generate=") )
+config.substitutions.append( ("%clangxx_pgogen ", build_invocation(clang_cxxflags) + " -fprofile-generate ") )
+config.substitutions.append( ("%clangxx_pgogen=", build_invocation(clang_cxxflags) + " -fprofile-generate=") )
+
config.substitutions.append( ("%clang_profgen_gcc=", build_invocation(clang_cflags) + " -fprofile-generate=") )
config.substitutions.append( ("%clang_profuse_gcc=", build_invocation(clang_cflags) + " -fprofile-use=") )
+config.substitutions.append( ("%clang_profuse=", build_invocation(clang_cflags) + " -fprofile-instr-use=") )
+config.substitutions.append( ("%clangxx_profuse=", build_invocation(clang_cxxflags) + " -fprofile-instr-use=") )
+
+config.substitutions.append( ("%clang_lto_profgen=", build_invocation(clang_cflags, True) + " -fprofile-instr-generate=") )
+
if config.host_os not in ['Darwin', 'FreeBSD', 'Linux']:
config.unsupported = True
diff --git a/test/safestack/lit.cfg b/test/safestack/lit.cfg
index 535c09742ca93..d4ec73ce703b0 100644
--- a/test/safestack/lit.cfg
+++ b/test/safestack/lit.cfg
@@ -16,7 +16,6 @@ config.substitutions.append( ("%clang_nosafestack ", config.clang + " -O0 -fno-s
config.substitutions.append( ("%clang_safestack ", config.clang + " -O0 -fsanitize=safe-stack ") )
if config.lto_supported:
- config.available_features.add('lto')
config.substitutions.append((r"%clang_lto_safestack ", ' '.join(config.lto_launch + [config.clang] + config.lto_flags + ['-flto -fsanitize=safe-stack '])))
# SafeStack tests are currently supported on Linux, FreeBSD and Darwin only.
diff --git a/test/sanitizer_common/CMakeLists.txt b/test/sanitizer_common/CMakeLists.txt
index 9f121654318f9..9b4070b0f6eb5 100644
--- a/test/sanitizer_common/CMakeLists.txt
+++ b/test/sanitizer_common/CMakeLists.txt
@@ -27,14 +27,7 @@ foreach(tool ${SUPPORTED_TOOLS})
foreach(arch ${TEST_ARCH})
set(SANITIZER_COMMON_LIT_TEST_MODE ${tool})
set(SANITIZER_COMMON_TEST_TARGET_ARCH ${arch})
- if(${arch} MATCHES "arm|aarch64")
- # This is only true if we're cross-compiling.
- set(SANITIZER_COMMON_TEST_TARGET_CFLAGS
- ${COMPILER_RT_TEST_COMPILER_CFLAGS})
- else()
- get_target_flags_for_arch(${arch} SANITIZER_COMMON_TEST_TARGET_CFLAGS)
- string(REPLACE ";" " " SANITIZER_COMMON_TEST_TARGET_CFLAGS "${SANITIZER_COMMON_TEST_TARGET_CFLAGS}")
- endif()
+ get_test_cc_for_arch(${arch} SANITIZER_COMMON_TEST_TARGET_CC SANITIZER_COMMON_TEST_TARGET_CFLAGS)
set(CONFIG_NAME ${tool}-${arch}-${OS_NAME})
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
@@ -53,9 +46,7 @@ if(COMPILER_RT_INCLUDE_TESTS)
list(APPEND SANITIZER_COMMON_TEST_DEPS SanitizerUnitTests)
endif()
-# FIXME: Re-enable on 64-bit Windows.
-if(SANITIZER_COMMON_TESTSUITES AND
- (NOT OS_NAME MATCHES "Windows" OR CMAKE_SIZEOF_VOID_P EQUAL 4))
+if(SANITIZER_COMMON_TESTSUITES)
add_lit_testsuite(check-sanitizer "Running sanitizer_common tests"
${SANITIZER_COMMON_TESTSUITES}
DEPENDS ${SANITIZER_COMMON_TEST_DEPS})
diff --git a/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc b/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc
index d329122ae7f88..83570a9f13a44 100644
--- a/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc
+++ b/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc
@@ -8,6 +8,7 @@
// This run uses getrusage. We can only test getrusage when allocator_may_return_null=0
// because getrusage gives us max-rss, not current-rss.
// RUN: %env_tool_opts=soft_rss_limit_mb=220:quarantine_size=1:allocator_may_return_null=0:can_use_proc_maps_statm=0 not %run %t 2>&1 | FileCheck %s -check-prefix=CHECK_MAY_RETURN_0
+// REQUIRES: stable-runtime
// FIXME: make it work for other sanitizers.
// XFAIL: lsan
diff --git a/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc b/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc
index 88d41b6d5fea6..261295790836f 100644
--- a/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc
+++ b/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc
@@ -1,10 +1,10 @@
// Test dedup_token_length
// RUN: %clangxx -O0 %s -o %t
-// RUN: env %tool_options='abort_on_error=0' not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
-// RUN: env %tool_options='abort_on_error=0, dedup_token_length=0' not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
-// RUN: env %tool_options='abort_on_error=0, dedup_token_length=1' not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
-// RUN: env %tool_options='abort_on_error=0, dedup_token_length=2' not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
-// RUN: env %tool_options='abort_on_error=0, dedup_token_length=3' not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3
+// RUN: env %tool_options='abort_on_error=0' not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0 --match-full-lines
+// RUN: env %tool_options='abort_on_error=0, dedup_token_length=0' not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0 --match-full-lines
+// RUN: env %tool_options='abort_on_error=0, dedup_token_length=1' not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --match-full-lines
+// RUN: env %tool_options='abort_on_error=0, dedup_token_length=2' not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2 --match-full-lines
+// RUN: env %tool_options='abort_on_error=0, dedup_token_length=3' not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 --match-full-lines
// REQUIRES: stable-runtime
// FIXME: implement SEGV handler in other sanitizers, not just asan.
@@ -34,7 +34,5 @@ int main(int argc, char **argv) {
// CHECK0-NOT: DEDUP_TOKEN:
// CHECK1: DEDUP_TOKEN: void Xyz::Abc<int, int>()
-// CHECK1-NOT: bar
// CHECK2: DEDUP_TOKEN: void Xyz::Abc<int, int>()--bar
-// CHECK2-NOT: FOO
// CHECK3: DEDUP_TOKEN: void Xyz::Abc<int, int>()--bar--FOO()
diff --git a/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc b/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc
new file mode 100644
index 0000000000000..f5a18e6721cf5
--- /dev/null
+++ b/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc
@@ -0,0 +1,63 @@
+// RUN: %clangxx -DSHARED %s -shared -o %T/get_module_and_offset_for_pc.so -fPIC
+// RUN: %clangxx -DSO_DIR=\"%T\" -O0 %s -ldl -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: i386-darwin
+//
+// Tests __sanitizer_get_module_and_offset_for_pc.
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <sanitizer/common_interface_defs.h>
+#include <stdio.h>
+
+#ifdef SHARED
+extern "C" {
+int foo() { return 1; }
+}
+#else
+
+void Test(void *pc, const char *name) {
+ char module_name[1024];
+ void *offset;
+ int ok = __sanitizer_get_module_and_offset_for_pc(
+ pc, module_name, sizeof(module_name), &offset);
+ if (!ok) {
+ printf("NOT FOUND %s: %p\n", name, pc);
+ } else {
+ printf("FOUND %s: %s %p\n", name, module_name, offset);
+ }
+}
+
+void TestCallerPc() { Test(__builtin_return_address(0), "callerpc"); }
+
+void TestDlsym() {
+ void *handle = dlopen(SO_DIR "/get_module_and_offset_for_pc.so", RTLD_LAZY);
+ assert(handle);
+ void *foo = dlsym(handle, "foo");
+ assert(foo);
+ Test(foo, "foo");
+ dlclose(handle);
+}
+
+// Call __sanitizer_get_module_and_offset_for_pc lots of times
+// to make sure it is not too slow.
+void TestLoop() {
+ void *pc = __builtin_return_address(0);
+ char module_name[1024];
+ void *offset;
+ for (int i = 0; i < 1000000; ++i) {
+ __sanitizer_get_module_and_offset_for_pc(pc, module_name,
+ sizeof(module_name), &offset);
+ }
+}
+
+int main() {
+ Test(0, "null");
+ TestCallerPc();
+ TestDlsym();
+ TestLoop();
+}
+#endif
+// CHECK: NOT FOUND null: {{.*}}
+// CHECK-NEXT: FOUND callerpc: {{.*}}/get_module_and_offset_for_pc.cc.tmp {{.*}}
+// CHECK-NEXT: FOUND foo: {{.*}}/get_module_and_offset_for_pc.so {{.*}}
diff --git a/test/sanitizer_common/TestCases/printf-ldbl.c b/test/sanitizer_common/TestCases/printf-ldbl.c
new file mode 100644
index 0000000000000..f6629ab81c3b3
--- /dev/null
+++ b/test/sanitizer_common/TestCases/printf-ldbl.c
@@ -0,0 +1,13 @@
+// RUN: %clang %s -o %t && %run %t 2>&1
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char **argv) {
+ char buf[20];
+ long double ld = 4.0;
+ snprintf(buf, sizeof buf, "%Lf %d", ld, 123);
+ assert(!strcmp(buf, "4.000000 123"));
+ return 0;
+}
diff --git a/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc b/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc
new file mode 100644
index 0000000000000..cf16ec3833123
--- /dev/null
+++ b/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc
@@ -0,0 +1,72 @@
+// Tests trace pc guard coverage collection.
+//
+// REQUIRES: has_sancovcc,stable-runtime
+// XFAIL: tsan,darwin,powerpc64,s390x
+//
+// RUN: DIR=%t_workdir
+// RUN: CLANG_ARGS="-O0 -fsanitize-coverage=trace-pc-guard"
+// RUN: rm -rf $DIR
+// RUN: mkdir -p $DIR
+// RUN: cd $DIR
+// RUN: %clangxx -DSHARED1 $CLANG_ARGS -shared %s -o %t_1.so -fPIC
+// RUN: %clangxx -DSHARED2 $CLANG_ARGS -shared %s -o %t_2.so -fPIC
+// RUN: %clangxx -DMAIN $CLANG_ARGS %s -o %t %t_1.so %t_2.so
+// RUN: %env_tool_opts=coverage=1 %t 2>&1 | FileCheck %s
+// RUN: %sancovcc -covered-functions -strip_path_prefix=TestCases/ *.sancov \
+// RUN: %t %t_1.so %t_2.so 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-SANCOV %s
+// RUN: rm -rf $DIR
+
+#include <stdio.h>
+
+extern "C" {
+ int bar();
+ int baz();
+}
+
+#ifdef MAIN
+
+int foo() {
+ fprintf(stderr, "foo\n");
+ return 1;
+}
+
+int main() {
+ fprintf(stderr, "main\n");
+ foo();
+ bar();
+ baz();
+}
+
+#endif // MAIN
+
+extern "C" {
+
+#ifdef SHARED1
+int bar() {
+ fprintf(stderr, "bar\n");
+ return 1;
+}
+#endif
+
+#ifdef SHARED2
+int baz() {
+ fprintf(stderr, "baz\n");
+ return 1;
+}
+#endif
+
+} // extern "C"
+
+// CHECK: main
+// CHECK-NEXT: foo
+// CHECK-NEXT: bar
+// CHECK-NEXT: baz
+// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}.sancov 2 PCs written
+// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_2.so.{{.*}}.sancov 1 PCs written
+// CHECK-DAG: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_1.so.{{.*}}.sancov 1 PCs written
+//
+// CHECK-SANCOV: Ignoring {{.*}}_1.so and its coverage because __sanitizer_cov* functions were not found.
+// CHECK-SANCOV: Ignoring {{.*}}_2.so and its coverage because __sanitizer_cov* functions were not found.
+// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard-dso.cc:29 foo
+// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard-dso.cc:34 main
diff --git a/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc b/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc
new file mode 100644
index 0000000000000..1b787f143d467
--- /dev/null
+++ b/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc
@@ -0,0 +1,41 @@
+// Tests trace pc guard coverage collection.
+//
+// REQUIRES: has_sancovcc,stable-runtime
+// XFAIL: tsan,darwin,powerpc64,s390x
+//
+// RUN: DIR=%t_workdir
+// RUN: rm -rf $DIR
+// RUN: mkdir -p $DIR
+// RUN: cd $DIR
+// RUN: %clangxx -O0 -fsanitize-coverage=trace-pc-guard %s -ldl -o %t
+// RUN: %env_tool_opts=coverage=1 %t 2>&1 | FileCheck %s
+// RUN: %sancovcc -covered-functions -strip_path_prefix=TestCases/ *.sancov %t 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-SANCOV %s
+// RUN: %env_tool_opts=coverage=0 %t 2>&1 | FileCheck --check-prefix=CHECK-NOCOV %s
+// RUN: rm -rf $DIR
+// Make some room to stabilize line numbers
+//
+//
+//
+#include <stdio.h>
+
+int foo() {
+ fprintf(stderr, "foo\n");
+ return 1;
+}
+
+int main() {
+ fprintf(stderr, "main\n");
+ foo();
+ foo();
+}
+
+// CHECK: main
+// CHECK-NEXT: foo
+// CHECK-NEXT: foo
+// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard.{{.*}}.sancov 2 PCs written
+//
+// CHECK-SANCOV: sanitizer_coverage_trace_pc_guard.cc:22 foo
+// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard.cc:27 main
+//
+// CHECK-NOCOV-NOT: SanitizerCoverage
diff --git a/test/sanitizer_common/TestCases/scanf-ldbl.c b/test/sanitizer_common/TestCases/scanf-ldbl.c
new file mode 100644
index 0000000000000..9ca30f4a65688
--- /dev/null
+++ b/test/sanitizer_common/TestCases/scanf-ldbl.c
@@ -0,0 +1,13 @@
+// RUN: %clang %s -o %t && %run %t 2>&1
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char **argv) {
+ long double ld;
+ memset(&ld, 255, sizeof ld);
+ sscanf("4.0", "%Lf", &ld);
+ assert(ld == 4.0);
+ return 0;
+}
diff --git a/test/sanitizer_common/TestCases/symbolize_pc.cc b/test/sanitizer_common/TestCases/symbolize_pc.cc
new file mode 100644
index 0000000000000..0cc81e1f7dcfb
--- /dev/null
+++ b/test/sanitizer_common/TestCases/symbolize_pc.cc
@@ -0,0 +1,41 @@
+// RUN: %clangxx -O0 %s -o %t
+// RUN: %env_tool_opts=strip_path_prefix=/TestCases/ %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: i386-darwin
+//
+// Tests __sanitizer_symbolize_pc.
+#include <stdio.h>
+#include <sanitizer/common_interface_defs.h>
+
+int GLOBAL_VAR_ABC;
+
+void SymbolizeCaller() {
+ char data[100];
+ __sanitizer_symbolize_pc(__builtin_return_address(0), "%p %F %L", data,
+ sizeof(data));
+ printf("FIRST_FORMAT %s\n", data);
+ __sanitizer_symbolize_pc(__builtin_return_address(0),
+ "FUNC:%f LINE:%l FILE:%s", data, sizeof(data));
+ printf("SECOND_FORMAT %s\n", data);
+ __sanitizer_symbolize_pc(__builtin_return_address(0),
+ "LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"
+ "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"
+ "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"
+ "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"
+ "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG"
+ "FUNC:%f LINE:%l FILE:%s", data, sizeof(data));
+ printf("LONG_FORMAT %s\n", data);
+}
+
+void SymbolizeData() {
+ char data[100];
+ __sanitizer_symbolize_global(&GLOBAL_VAR_ABC, "%g %s:%l", data, sizeof(data));
+ printf("GLOBAL: %s\n", data);
+}
+
+// CHECK: FIRST_FORMAT 0x{{.*}} in main symbolize_pc.cc:[[@LINE+3]]
+// CHECK: SECOND_FORMAT FUNC:main LINE:[[@LINE+2]] FILE:symbolize_pc.cc
+int main() {
+ SymbolizeCaller();
+ SymbolizeData();
+}
+// CHECK: GLOBAL: GLOBAL_VAR_ABC
diff --git a/test/sanitizer_common/print_address.h b/test/sanitizer_common/print_address.h
new file mode 100644
index 0000000000000..018db61800d3e
--- /dev/null
+++ b/test/sanitizer_common/print_address.h
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+void print_address(const char *str, int n, ...) {
+ fprintf(stderr, "%s", str);
+ va_list ap;
+ va_start(ap, n);
+ while (n--) {
+ void *p = va_arg(ap, void *);
+#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__)
+ // On FreeBSD, the %p conversion specifier works as 0x%x and thus does not
+ // match to the format used in the diagnotic message.
+ fprintf(stderr, "0x%012lx ", (unsigned long) p);
+#elif defined(__mips64)
+ fprintf(stderr, "0x%010lx ", (unsigned long) p);
+#endif
+ }
+ fprintf(stderr, "\n");
+}
diff --git a/test/scudo/CMakeLists.txt b/test/scudo/CMakeLists.txt
index b6cb2fd24f012..a8990999722e1 100644
--- a/test/scudo/CMakeLists.txt
+++ b/test/scudo/CMakeLists.txt
@@ -1,6 +1,7 @@
set(SCUDO_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(SCUDO_LIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+set(SCUDO_TESTSUITES)
set(SCUDO_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
if(NOT COMPILER_RT_STANDALONE_BUILD)
@@ -12,17 +13,21 @@ configure_lit_site_cfg(
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
)
-if(CMAKE_SYSTEM_NAME MATCHES "Linux")
- EXEC_PROGRAM(cat ARGS "/proc/cpuinfo" OUTPUT_VARIABLE CPUINFO)
- STRING(REGEX REPLACE "^.*(sse4_2).*$" "\\1" SSE_THERE ${CPUINFO})
- STRING(COMPARE EQUAL "sse4_2" "${SSE_THERE}" SSE42_TRUE)
-endif(CMAKE_SYSTEM_NAME MATCHES "Linux")
+set(SCUDO_TEST_ARCH ${SCUDO_SUPPORTED_ARCH})
+foreach(arch ${SCUDO_TEST_ARCH})
+ set(SCUDO_TEST_TARGET_ARCH ${arch})
+ string(TOLOWER "-${arch}" SCUDO_TEST_CONFIG_SUFFIX)
+ get_test_cc_for_arch(${arch} SCUDO_TEST_TARGET_CC SCUDO_TEST_TARGET_CFLAGS)
+ string(TOUPPER ${arch} ARCH_UPPER_CASE)
+ set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
-if (SSE42_TRUE AND CMAKE_SIZEOF_VOID_P EQUAL 8)
- add_lit_testsuite(check-scudo
- "Running the Scudo Hardened Allocator tests"
- ${CMAKE_CURRENT_BINARY_DIR}
- DEPENDS ${SCUDO_TEST_DEPS})
- set_target_properties(check-scudo PROPERTIES FOLDER
- "Compiler-RT Misc")
-endif(SSE42_TRUE AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
+ list(APPEND SCUDO_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+endforeach()
+
+add_lit_testsuite(check-scudo "Running the Scudo Hardened Allocator tests"
+ ${SCUDO_TESTSUITES}
+ DEPENDS ${SCUDO_TEST_DEPS})
+set_target_properties(check-scudo PROPERTIES FOLDER "Compiler-RT Misc")
diff --git a/test/scudo/alignment.cpp b/test/scudo/alignment.cpp
index c5e57d1799079..a6eca87a82248 100644
--- a/test/scudo/alignment.cpp
+++ b/test/scudo/alignment.cpp
@@ -1,11 +1,10 @@
// RUN: %clang_scudo %s -o %t
// RUN: not %run %t pointers 2>&1 | FileCheck %s
-// Tests that a non-16-byte aligned pointer will trigger the associated error
-// on deallocation.
+// Tests that a non MinAlignment aligned pointer will trigger the associated
+// error on deallocation.
#include <assert.h>
-#include <malloc.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -17,7 +16,7 @@ int main(int argc, char **argv)
void *p = malloc(1U << 16);
if (!p)
return 1;
- free(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p) | 8));
+ free(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p) | 1));
}
return 0;
}
diff --git a/test/scudo/double-free.cpp b/test/scudo/double-free.cpp
index 4f5bf0cb8e56a..75919f0c459c5 100644
--- a/test/scudo/double-free.cpp
+++ b/test/scudo/double-free.cpp
@@ -46,4 +46,4 @@ int main(int argc, char **argv)
return 0;
}
-// CHECK: ERROR: invalid chunk state when deallocating address
+// CHECK: ERROR: invalid chunk state
diff --git a/test/scudo/interface.cpp b/test/scudo/interface.cpp
new file mode 100644
index 0000000000000..f9353066efa37
--- /dev/null
+++ b/test/scudo/interface.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_scudo %s -o %t
+// RUN: %run %t 2>&1
+
+// Tests that the sanitizer interface functions behave appropriately.
+
+#include <stdlib.h>
+
+#include <vector>
+
+#include <sanitizer/allocator_interface.h>
+
+int main(int argc, char **argv)
+{
+ void *p;
+ std::vector<ssize_t> sizes{1, 8, 16, 32, 1024, 32768,
+ 1 << 16, 1 << 17, 1 << 20, 1 << 24};
+ for (size_t size : sizes) {
+ p = malloc(size);
+ if (!p)
+ return 1;
+ if (!__sanitizer_get_ownership(p))
+ return 1;
+ if (__sanitizer_get_allocated_size(p) < size)
+ return 1;
+ free(p);
+ }
+ return 0;
+}
diff --git a/test/scudo/lit.cfg b/test/scudo/lit.cfg
index e2a4997dd3c28..4eff2ce2191d0 100644
--- a/test/scudo/lit.cfg
+++ b/test/scudo/lit.cfg
@@ -3,7 +3,7 @@
import os
# Setup config name.
-config.name = 'Scudo'
+config.name = 'Scudo' + config.name_suffix
# Setup source root.
config.test_source_root = os.path.dirname(__file__)
@@ -14,18 +14,19 @@ base_lib = os.path.join(config.compiler_rt_libdir,
whole_archive = "-Wl,-whole-archive %s -Wl,-no-whole-archive " % base_lib
# Test suffixes.
-config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm', '.ll', '.test']
+config.suffixes = ['.c', '.cc', '.cpp']
# C flags.
-c_flags = ["-std=c++11",
+c_flags = ([config.target_cflags] +
+ ["-std=c++11",
"-lstdc++",
- "-ldl",
"-lrt",
- "-pthread",
"-latomic",
+ "-ldl",
+ "-pthread",
"-fPIE",
"-pie",
- "-O0"]
+ "-O0"])
def build_invocation(compile_flags):
return " " + " ".join([config.clang] + compile_flags) + " "
diff --git a/test/scudo/lit.site.cfg.in b/test/scudo/lit.site.cfg.in
index 64e2fb39eed8a..4299518755e98 100644
--- a/test/scudo/lit.site.cfg.in
+++ b/test/scudo/lit.site.cfg.in
@@ -1,5 +1,9 @@
@LIT_SITE_CFG_IN_HEADER@
+config.name_suffix = "@SCUDO_TEST_CONFIG_SUFFIX@"
+config.target_arch = "@SCUDO_TEST_TARGET_ARCH@"
+config.target_cflags = "@SCUDO_TEST_TARGET_CFLAGS@"
+
# Load common config for all compiler-rt lit tests.
lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
diff --git a/test/scudo/malloc.cpp b/test/scudo/malloc.cpp
index 4507a5225ceb7..cafc744a20c24 100644
--- a/test/scudo/malloc.cpp
+++ b/test/scudo/malloc.cpp
@@ -2,26 +2,37 @@
// RUN: %run %t 2>&1
// Tests that a regular workflow of allocation, memory fill and free works as
-// intended. Also tests that a zero-sized allocation succeeds.
+// intended. Tests various sizes serviced by the primary and secondary
+// allocators.
-#include <malloc.h>
#include <stdlib.h>
#include <string.h>
+#include <vector>
+
int main(int argc, char **argv)
{
void *p;
- size_t size = 1U << 8;
+ std::vector<ssize_t> sizes{1, 8, 16, 32, 1024, 32768,
+ 1 << 16, 1 << 17, 1 << 20, 1 << 24};
+ std::vector<int> offsets{1, 0, -1, -7, -8, -15, -16, -31, -32};
- p = malloc(size);
- if (!p)
- return 1;
- memset(p, 'A', size);
- free(p);
p = malloc(0);
if (!p)
return 1;
free(p);
+ for (ssize_t size : sizes) {
+ for (int offset: offsets) {
+ ssize_t actual_size = size + offset;
+ if (actual_size <= 0)
+ continue;
+ p = malloc(actual_size);
+ if (!p)
+ return 1;
+ memset(p, 0xff, actual_size);
+ free(p);
+ }
+ }
return 0;
}
diff --git a/test/scudo/memalign.cpp b/test/scudo/memalign.cpp
index 951d1aade6ec9..b407ec5743490 100644
--- a/test/scudo/memalign.cpp
+++ b/test/scudo/memalign.cpp
@@ -10,22 +10,24 @@
#include <stdlib.h>
#include <string.h>
+// Reduce the size of the quarantine, or the test can run out of aligned memory
+// on 32-bit for the larger alignments.
+extern "C" const char *__scudo_default_options() {
+ return "QuarantineSizeMb=1";
+}
+
// Sometimes the headers may not have this...
extern "C" void *aligned_alloc (size_t alignment, size_t size);
int main(int argc, char **argv)
{
- void *p;
+ void *p = nullptr;
size_t alignment = 1U << 12;
- size_t size = alignment;
+ size_t size = 1U << 12;
assert(argc == 2);
+
if (!strcmp(argv[1], "valid")) {
- p = memalign(alignment, size);
- if (!p)
- return 1;
- free(p);
- p = nullptr;
posix_memalign(&p, alignment, size);
if (!p)
return 1;
@@ -34,6 +36,29 @@ int main(int argc, char **argv)
if (!p)
return 1;
free(p);
+ // Tests various combinations of alignment and sizes
+ for (int i = (sizeof(void *) == 4) ? 3 : 4; i < 19; i++) {
+ alignment = 1U << i;
+ for (int j = 1; j < 33; j++) {
+ size = 0x800 * j;
+ for (int k = 0; k < 3; k++) {
+ p = memalign(alignment, size - (2 * sizeof(void *) * k));
+ if (!p)
+ return 1;
+ free(p);
+ }
+ }
+ }
+ // For larger alignment, reduce the number of allocations to avoid running
+ // out of potential addresses (on 32-bit).
+ for (int i = 19; i <= 24; i++) {
+ for (int k = 0; k < 3; k++) {
+ p = memalign(alignment, 0x1000 - (2 * sizeof(void *) * k));
+ if (!p)
+ return 1;
+ free(p);
+ }
+ }
}
if (!strcmp(argv[1], "invalid")) {
p = memalign(alignment - 1, size);
@@ -42,4 +67,4 @@ int main(int argc, char **argv)
return 0;
}
-// CHECK: ERROR: malloc alignment is not a power of 2
+// CHECK: ERROR: alignment is not a power of 2
diff --git a/test/scudo/mismatch.cpp b/test/scudo/mismatch.cpp
index 2d3d198af640a..54cdafc86ee67 100644
--- a/test/scudo/mismatch.cpp
+++ b/test/scudo/mismatch.cpp
@@ -30,7 +30,7 @@ int main(int argc, char **argv)
free((void *)p);
}
if (!strcmp(argv[1], "memaligndel")) {
- int *p = (int *)memalign(0x10, 0x10);
+ int *p = (int *)memalign(16, 16);
if (!p)
return 1;
delete p;
diff --git a/test/scudo/options.cpp b/test/scudo/options.cpp
new file mode 100644
index 0000000000000..bccf7c8fbd2b9
--- /dev/null
+++ b/test/scudo/options.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_scudo %s -o %t
+// RUN: %run %t 2>&1
+// RUN: SCUDO_OPTIONS=DeallocationTypeMismatch=0 %run %t 2>&1
+// RUN: SCUDO_OPTIONS=DeallocationTypeMismatch=1 not %run %t 2>&1 | FileCheck %s
+
+// Tests that the options can be passed using getScudoDefaultOptions, and that
+// the environment ones take precedence over them.
+
+#include <stdlib.h>
+#include <malloc.h>
+
+extern "C" const char* __scudo_default_options() {
+ return "DeallocationTypeMismatch=0"; // Defaults to true in scudo_flags.inc.
+}
+
+int main(int argc, char **argv)
+{
+ int *p = (int *)malloc(16);
+ if (!p)
+ return 1;
+ delete p;
+ return 0;
+}
+
+// CHECK: ERROR: allocation type mismatch on address
diff --git a/test/scudo/overflow.cpp b/test/scudo/overflow.cpp
index 5b2cb7560133a..c93a544ea0a07 100644
--- a/test/scudo/overflow.cpp
+++ b/test/scudo/overflow.cpp
@@ -11,12 +11,13 @@
int main(int argc, char **argv)
{
assert(argc == 2);
+ ssize_t offset = sizeof(void *) == 8 ? 8 : 0;
if (!strcmp(argv[1], "malloc")) {
// Simulate a header corruption of an allocated chunk (1-bit)
void *p = malloc(1U << 4);
if (!p)
return 1;
- ((char *)p)[-1] ^= 1;
+ ((char *)p)[-(offset + 1)] ^= 1;
free(p);
}
if (!strcmp(argv[1], "quarantine")) {
@@ -25,7 +26,7 @@ int main(int argc, char **argv)
return 1;
free(p);
// Simulate a header corruption of a quarantined chunk
- ((char *)p)[-2] ^= 1;
+ ((char *)p)[-(offset + 2)] ^= 1;
// Trigger the quarantine recycle
for (int i = 0; i < 0x100; i++) {
p = malloc(1U << 16);
diff --git a/test/scudo/preinit.cpp b/test/scudo/preinit.cpp
index a280ae1d440a9..34f61c9ddfbb4 100644
--- a/test/scudo/preinit.cpp
+++ b/test/scudo/preinit.cpp
@@ -4,7 +4,6 @@
// Verifies that calling malloc in a preinit_array function succeeds, and that
// the resulting pointer can be freed at program termination.
-#include <malloc.h>
#include <stdlib.h>
#include <string.h>
diff --git a/test/scudo/random_shuffle.cpp b/test/scudo/random_shuffle.cpp
new file mode 100644
index 0000000000000..fce522d9481c6
--- /dev/null
+++ b/test/scudo/random_shuffle.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_scudo %s -o %t
+// RUN: rm -rf %T/random_shuffle_tmp_dir
+// RUN: mkdir %T/random_shuffle_tmp_dir
+// RUN: %run %t 100 > %T/random_shuffle_tmp_dir/out1
+// RUN: %run %t 100 > %T/random_shuffle_tmp_dir/out2
+// RUN: %run %t 10000 > %T/random_shuffle_tmp_dir/out1
+// RUN: %run %t 10000 > %T/random_shuffle_tmp_dir/out2
+// RUN: not diff %T/random_shuffle_tmp_dir/out?
+// RUN: rm -rf %T/random_shuffle_tmp_dir
+// UNSUPPORTED: i386-linux,i686-linux,arm-linux,armhf-linux
+
+// Tests that the allocator shuffles the chunks before returning to the user.
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int main(int argc, char **argv) {
+ int alloc_size = argc == 2 ? atoi(argv[1]) : 100;
+ char *base = new char[alloc_size];
+ for (int i = 0; i < 20; i++) {
+ char *p = new char[alloc_size];
+ printf("%zd\n", base - p);
+ }
+}
diff --git a/test/scudo/realloc.cpp b/test/scudo/realloc.cpp
index 2a7d5b69f5f20..cc44595001f43 100644
--- a/test/scudo/realloc.cpp
+++ b/test/scudo/realloc.cpp
@@ -14,54 +14,60 @@
#include <malloc.h>
#include <string.h>
+#include <vector>
+
int main(int argc, char **argv)
{
void *p, *old_p;
- size_t size = 32;
+ // Those sizes will exercise both allocators (Primary & Secondary).
+ std::vector<size_t> sizes{1, 16, 1024, 32768, 1 << 16, 1 << 17, 1 << 20};
assert(argc == 2);
- if (!strcmp(argv[1], "pointers")) {
- old_p = p = realloc(nullptr, size);
- if (!p)
- return 1;
- size = malloc_usable_size(p);
- // Our realloc implementation will return the same pointer if the size
- // requested is lower or equal to the usable size of the associated chunk.
- p = realloc(p, size - 1);
- if (p != old_p)
- return 1;
- p = realloc(p, size);
- if (p != old_p)
- return 1;
- // And a new one if the size is greater.
- p = realloc(p, size + 1);
- if (p == old_p)
- return 1;
- // A size of 0 will free the chunk and return nullptr.
- p = realloc(p, 0);
- if (p)
- return 1;
- old_p = nullptr;
- }
- if (!strcmp(argv[1], "contents")) {
- p = realloc(nullptr, size);
- if (!p)
- return 1;
- for (int i = 0; i < size; i++)
- reinterpret_cast<char *>(p)[i] = 'A';
- p = realloc(p, size + 1);
- // The contents of the reallocated chunk must match the original one.
- for (int i = 0; i < size; i++)
- if (reinterpret_cast<char *>(p)[i] != 'A')
+ for (size_t size : sizes) {
+ if (!strcmp(argv[1], "pointers")) {
+ old_p = p = realloc(nullptr, size);
+ if (!p)
return 1;
- }
- if (!strcmp(argv[1], "memalign")) {
- // A chunk coming from memalign cannot be reallocated.
- p = memalign(16, size);
- if (!p)
- return 1;
- p = realloc(p, size);
- free(p);
+ size = malloc_usable_size(p);
+ // Our realloc implementation will return the same pointer if the size
+ // requested is lower than or equal to the usable size of the associated
+ // chunk.
+ p = realloc(p, size - 1);
+ if (p != old_p)
+ return 1;
+ p = realloc(p, size);
+ if (p != old_p)
+ return 1;
+ // And a new one if the size is greater.
+ p = realloc(p, size + 1);
+ if (p == old_p)
+ return 1;
+ // A size of 0 will free the chunk and return nullptr.
+ p = realloc(p, 0);
+ if (p)
+ return 1;
+ old_p = nullptr;
+ }
+ if (!strcmp(argv[1], "contents")) {
+ p = realloc(nullptr, size);
+ if (!p)
+ return 1;
+ for (int i = 0; i < size; i++)
+ reinterpret_cast<char *>(p)[i] = 'A';
+ p = realloc(p, size + 1);
+ // The contents of the reallocated chunk must match the original one.
+ for (int i = 0; i < size; i++)
+ if (reinterpret_cast<char *>(p)[i] != 'A')
+ return 1;
+ }
+ if (!strcmp(argv[1], "memalign")) {
+ // A chunk coming from memalign cannot be reallocated.
+ p = memalign(16, size);
+ if (!p)
+ return 1;
+ p = realloc(p, size);
+ free(p);
+ }
}
return 0;
}
diff --git a/test/scudo/secondary.cpp b/test/scudo/secondary.cpp
new file mode 100644
index 0000000000000..7a634a81eb03e
--- /dev/null
+++ b/test/scudo/secondary.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_scudo %s -o %t
+// RUN: %run %t after 2>&1 | FileCheck %s
+// RUN: %run %t before 2>&1 | FileCheck %s
+
+// Test that we hit a guard page when writing past the end of a chunk
+// allocated by the Secondary allocator, or writing too far in front of it.
+
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <assert.h>
+
+void handler(int signo, siginfo_t *info, void *uctx) {
+ if (info->si_code == SEGV_ACCERR) {
+ fprintf(stderr, "SCUDO SIGSEGV\n");
+ exit(0);
+ }
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ // The size must be large enough to be serviced by the secondary allocator.
+ long page_size = sysconf(_SC_PAGESIZE);
+ size_t size = (1U << 17) + page_size;
+ struct sigaction a;
+
+ assert(argc == 2);
+ memset(&a, 0, sizeof(a));
+ a.sa_sigaction = handler;
+ a.sa_flags = SA_SIGINFO;
+
+ char *p = (char *)malloc(size);
+ if (!p)
+ return 1;
+ memset(p, 'A', size); // This should not trigger anything.
+ // Set up the SIGSEGV handler now, as the rest should trigger an AV.
+ sigaction(SIGSEGV, &a, nullptr);
+ if (!strcmp(argv[1], "after")) {
+ for (int i = 0; i < page_size; i++)
+ p[size + i] = 'A';
+ }
+ if (!strcmp(argv[1], "before")) {
+ for (int i = 1; i < page_size; i++)
+ p[-i] = 'A';
+ }
+ free(p);
+
+ return 1; // A successful test means we shouldn't reach this.
+}
+
+// CHECK: SCUDO SIGSEGV
diff --git a/test/tsan/CMakeLists.txt b/test/tsan/CMakeLists.txt
index e05b100f36995..2db6ce0a8c1a4 100644
--- a/test/tsan/CMakeLists.txt
+++ b/test/tsan/CMakeLists.txt
@@ -24,15 +24,7 @@ endif()
foreach(arch ${TSAN_TEST_ARCH})
set(TSAN_TEST_TARGET_ARCH ${arch})
string(TOLOWER "-${arch}" TSAN_TEST_CONFIG_SUFFIX)
- if(ANDROID OR ${arch} MATCHES "arm|aarch64")
- # This is only true if we are cross-compiling.
- # Build all tests with host compiler and use host tools.
- set(TSAN_TEST_TARGET_CC ${COMPILER_RT_TEST_COMPILER})
- set(TSAN_TEST_TARGET_CFLAGS ${COMPILER_RT_TEST_COMPILER_CFLAGS})
- else()
- get_target_flags_for_arch(${arch} TSAN_TEST_TARGET_CFLAGS)
- string(REPLACE ";" " " TSAN_TEST_TARGET_CFLAGS "${TSAN_TEST_TARGET_CFLAGS}")
- endif()
+ get_test_cc_for_arch(${arch} TSAN_TEST_TARGET_CC TSAN_TEST_TARGET_CFLAGS)
string(TOUPPER ${arch} ARCH_UPPER_CASE)
set(CONFIG_NAME ${ARCH_UPPER_CASE}Config)
diff --git a/test/tsan/Darwin/gcd-apply-race.mm b/test/tsan/Darwin/gcd-apply-race.mm
index 13b24e0fdb90e..028be1ac5b1cc 100644
--- a/test/tsan/Darwin/gcd-apply-race.mm
+++ b/test/tsan/Darwin/gcd-apply-race.mm
@@ -10,6 +10,10 @@ long global;
int main(int argc, const char *argv[]) {
barrier_init(&barrier, 2);
fprintf(stderr, "start\n");
+
+ // Warm up GCD (workaround for macOS Sierra where dispatch_apply might run single-threaded).
+ dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ });
+
dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_apply(2, q, ^(size_t i) {
global = i;
diff --git a/test/tsan/Darwin/gcd-apply.mm b/test/tsan/Darwin/gcd-apply.mm
index e68a4b18205d9..a7dc3740dc7b5 100644
--- a/test/tsan/Darwin/gcd-apply.mm
+++ b/test/tsan/Darwin/gcd-apply.mm
@@ -17,6 +17,10 @@ void callback(void *context, size_t i) {
int main(int argc, const char *argv[]) {
barrier_init(&barrier, 2);
fprintf(stderr, "start\n");
+
+ // Warm up GCD (workaround for macOS Sierra where dispatch_apply might run single-threaded).
+ dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ });
+
dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT);
global = 42;
diff --git a/test/tsan/Darwin/gcd-suspend.mm b/test/tsan/Darwin/gcd-suspend.mm
new file mode 100644
index 0000000000000..3e8818a2d56e7
--- /dev/null
+++ b/test/tsan/Darwin/gcd-suspend.mm
@@ -0,0 +1,45 @@
+// RUN: %clang_tsan %s -o %t -framework Foundation
+// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+
+long my_global = 0;
+
+int main(int argc, const char *argv[]) {
+ fprintf(stderr, "Hello world.\n");
+
+ dispatch_queue_t q1 = dispatch_queue_create("queue1", NULL);
+ dispatch_queue_t q2 = dispatch_queue_create("queue2", NULL);
+ dispatch_group_t g = dispatch_group_create();
+
+ dispatch_sync(q1, ^{
+ dispatch_suspend(q1);
+ dispatch_async(q2, ^{
+ my_global++;
+ dispatch_resume(q1);
+ });
+ });
+
+ dispatch_sync(q1, ^{
+ my_global++;
+ });
+
+ dispatch_sync(q1, ^{
+ dispatch_suspend(q1);
+ dispatch_group_enter(g);
+ dispatch_async(q1,^{ my_global++; });
+ dispatch_async(q1,^{ my_global++; });
+ dispatch_async(q1,^{ my_global++; dispatch_group_leave(g); });
+ my_global++;
+ dispatch_resume(q1);
+ });
+
+ dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
+
+ fprintf(stderr, "Done.\n");
+ return 0;
+}
+
+// CHECK: Hello world.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.
diff --git a/test/tsan/Darwin/gcd-target-queue-norace.mm b/test/tsan/Darwin/gcd-target-queue-norace.mm
new file mode 100644
index 0000000000000..36cb1b9298de0
--- /dev/null
+++ b/test/tsan/Darwin/gcd-target-queue-norace.mm
@@ -0,0 +1,41 @@
+// RUN: %clang_tsan %s -o %t -framework Foundation
+// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+
+long global;
+
+int main(int argc, const char *argv[]) {
+ dispatch_queue_t target_queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
+ dispatch_queue_t q1 = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
+ dispatch_queue_t q2 = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
+ dispatch_set_target_queue(q1, target_queue);
+ dispatch_set_target_queue(q2, target_queue);
+
+ for (int i = 0; i < 100000; i++) {
+ dispatch_async(q1, ^{
+ global++;
+
+ if (global == 200000) {
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ CFRunLoopStop(CFRunLoopGetCurrent());
+ });
+ }
+ });
+ dispatch_async(q2, ^{
+ global++;
+
+ if (global == 200000) {
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ CFRunLoopStop(CFRunLoopGetCurrent());
+ });
+ }
+ });
+ }
+
+ CFRunLoopRun();
+ NSLog(@"Done.");
+ return 0;
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer
diff --git a/test/tsan/Darwin/libcxx-call-once.mm b/test/tsan/Darwin/libcxx-call-once.mm
new file mode 100644
index 0000000000000..5388e495c9c26
--- /dev/null
+++ b/test/tsan/Darwin/libcxx-call-once.mm
@@ -0,0 +1,34 @@
+// RUN: %clangxx_tsan %s -o %t -framework Foundation -std=c++11
+// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+
+#import <iostream>
+#import <thread>
+
+long my_global;
+std::once_flag once_token;
+
+void thread_func() {
+ std::call_once(once_token, [] {
+ my_global = 17;
+ });
+
+ long val = my_global;
+ fprintf(stderr, "my_global = %ld\n", val);
+}
+
+int main(int argc, const char *argv[]) {
+ fprintf(stderr, "Hello world.\n");
+
+ std::thread t1(thread_func);
+ std::thread t2(thread_func);
+ t1.join();
+ t2.join();
+
+ fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.
diff --git a/test/tsan/Darwin/libcxx-future.mm b/test/tsan/Darwin/libcxx-future.mm
new file mode 100644
index 0000000000000..902f267ecb89d
--- /dev/null
+++ b/test/tsan/Darwin/libcxx-future.mm
@@ -0,0 +1,30 @@
+// RUN: %clangxx_tsan %s -o %t
+// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+
+#include <iostream>
+#include <future>
+#include <vector>
+
+int main(int argc, const char *argv[]) {
+ fprintf(stderr, "Hello world.\n");
+
+ auto my_task = [] { return 42; };
+
+ std::vector<std::thread> threads;
+
+ for (int i = 0; i < 100; i++) {
+ std::packaged_task<int(void)> task(my_task);
+ std::future<int> future = task.get_future();
+ threads.push_back(std::thread(std::move(task)));
+ }
+
+ for (auto &t : threads) {
+ t.join();
+ }
+
+ fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.
diff --git a/test/tsan/Darwin/norace-objcxx-run-time.mm b/test/tsan/Darwin/norace-objcxx-run-time.mm
new file mode 100644
index 0000000000000..0cf729e7f2d87
--- /dev/null
+++ b/test/tsan/Darwin/norace-objcxx-run-time.mm
@@ -0,0 +1,113 @@
+// RUN: %clang_tsan %s -lc++ -fobjc-arc -lobjc -o %t -framework Foundation
+// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+
+// Check that we do not report races between:
+// - Object retain and initialize
+// - Object release and dealloc
+// - Object release and .cxx_destruct
+
+#import <Foundation/Foundation.h>
+#include "../test.h"
+invisible_barrier_t barrier2;
+
+class NeedCleanup {
+ public:
+ int x;
+ NeedCleanup() {
+ x = 1;
+ }
+ ~NeedCleanup() {
+ x = 0;
+ }
+};
+
+@interface TestDeallocObject : NSObject {
+ @public
+ int v;
+ }
+ - (id)init;
+ - (void)accessMember;
+ - (void)dealloc;
+@end
+
+@implementation TestDeallocObject
+ - (id)init {
+ if ([super self]) {
+ v = 1;
+ return self;
+ }
+ return nil;
+ }
+ - (void)accessMember {
+ int local = v;
+ local++;
+ }
+ - (void)dealloc {
+ v = 0;
+ }
+@end
+
+@interface TestCXXDestructObject : NSObject {
+ @public
+ NeedCleanup cxxMemberWithCleanup;
+ }
+ - (void)accessMember;
+@end
+
+@implementation TestCXXDestructObject
+ - (void)accessMember {
+ int local = cxxMemberWithCleanup.x;
+ local++;
+ }
+@end
+
+@interface TestInitializeObject : NSObject
+@end
+
+@implementation TestInitializeObject
+ static long InitializerAccessedGlobal = 0;
+ + (void)initialize {
+ InitializerAccessedGlobal = 42;
+ }
+@end
+
+int main(int argc, const char *argv[]) {
+ // Ensure that there is no race when calling initialize on TestInitializeObject;
+ // otherwise, the locking from ObjC runtime becomes observable. Also ensures that
+ // blocks are dispatched to 2 different threads.
+ barrier_init(&barrier, 2);
+ // Ensure that objects are destructed during block object release.
+ barrier_init(&barrier2, 3);
+
+ TestDeallocObject *tdo = [[TestDeallocObject alloc] init];
+ TestCXXDestructObject *tcxxdo = [[TestCXXDestructObject alloc] init];
+ [tdo accessMember];
+ [tcxxdo accessMember];
+ {
+ dispatch_queue_t q = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
+ dispatch_async(q, ^{
+ [TestInitializeObject new];
+ barrier_wait(&barrier);
+ long local = InitializerAccessedGlobal;
+ local++;
+ [tdo accessMember];
+ [tcxxdo accessMember];
+ barrier_wait(&barrier2);
+ });
+ dispatch_async(q, ^{
+ barrier_wait(&barrier);
+ [TestInitializeObject new];
+ long local = InitializerAccessedGlobal;
+ local++;
+ [tdo accessMember];
+ [tcxxdo accessMember];
+ barrier_wait(&barrier2);
+ });
+ }
+ barrier_wait(&barrier2);
+ NSLog(@"Done.");
+ return 0;
+}
+
+// CHECK: Done.
+// CHECK-NOT: ThreadSanitizer: data race
diff --git a/test/tsan/Darwin/objc-double-property.mm b/test/tsan/Darwin/objc-double-property.mm
new file mode 100644
index 0000000000000..51b10f21c9cae
--- /dev/null
+++ b/test/tsan/Darwin/objc-double-property.mm
@@ -0,0 +1,21 @@
+// RUN: %clangxx_tsan -O0 %s -o %t -framework Foundation && %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_tsan -O1 %s -o %t -framework Foundation && %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_tsan -O2 %s -o %t -framework Foundation && %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_tsan -O3 %s -o %t -framework Foundation && %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+
+@interface MyClass : NSObject
+@property float a;
+@property double b;
+@property long double c;
+@end
+
+@implementation MyClass
+@end
+
+int main() {
+ NSLog(@"Hello world");
+}
+
+// CHECK: Hello world
diff --git a/test/tsan/Darwin/osatomics-bitops.mm b/test/tsan/Darwin/osatomics-bitops.mm
new file mode 100644
index 0000000000000..68badb792fd66
--- /dev/null
+++ b/test/tsan/Darwin/osatomics-bitops.mm
@@ -0,0 +1,34 @@
+// RUN: %clangxx_tsan %s -o %t -framework Foundation -std=c++11
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+#import <libkern/OSAtomic.h>
+
+int main(int argc, const char *argv[]) {
+ int value = 1;
+ bool ret = OSAtomicTestAndClear(7, &value);
+ fprintf(stderr, "value = %d, ret = %d\n", value, ret);
+ // CHECK: value = 0, ret = 1
+
+ ret = OSAtomicTestAndSet(4, &value);
+ fprintf(stderr, "value = %d, ret = %d\n", value, ret);
+ // CHECK: value = 8, ret = 0
+
+ ret = OSAtomicTestAndClear(4, &value);
+ fprintf(stderr, "value = %d, ret = %d\n", value, ret);
+ // CHECK: value = 0, ret = 1
+
+ ret = OSAtomicTestAndSet(12, &value);
+ fprintf(stderr, "value = %d, ret = %d\n", value, ret);
+ // CHECK: value = 2048, ret = 0
+
+ ret = OSAtomicTestAndSet(13, &value);
+ fprintf(stderr, "value = %d, ret = %d\n", value, ret);
+ // CHECK: value = 3072, ret = 0
+
+ ret = OSAtomicTestAndClear(12, &value);
+ fprintf(stderr, "value = %d, ret = %d\n", value, ret);
+ // CHECK: value = 1024, ret = 1
+
+ return 0;
+}
diff --git a/test/tsan/Darwin/realloc-zero.cc b/test/tsan/Darwin/realloc-zero.cc
new file mode 100644
index 0000000000000..98262463cb2d1
--- /dev/null
+++ b/test/tsan/Darwin/realloc-zero.cc
@@ -0,0 +1,20 @@
+// Test that realloc(nullptr, 0) return a non-NULL pointer.
+
+// RUN: %clang_tsan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <malloc/malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+int main() {
+ void *p = realloc(NULL, 0);
+ if (!p) {
+ abort();
+ }
+ fprintf(stderr, "Okay.\n");
+ return 0;
+}
+
+// CHECK: Okay.
diff --git a/test/tsan/atomic_free.cc b/test/tsan/atomic_free.cc
index a0d8e426b49fc..446949ddb986b 100644
--- a/test/tsan/atomic_free.cc
+++ b/test/tsan/atomic_free.cc
@@ -1,4 +1,13 @@
-// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
+// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s
+
+// Also check that atomics instrumentation can be configured by either driver or
+// legacy flags:
+
+// RUN: %clangxx_tsan -O1 %s -o %t -fno-sanitize-thread-atomics && not %deflake %run %t 2>&1 \
+// RUN: | FileCheck --allow-empty --check-prefix=CHECK-NO-ATOMICS %s
+// RUN: %clangxx_tsan -O1 %s -o %t -mllvm -tsan-instrument-atomics=0 && not %deflake %run %t 2>&1 \
+// RUN: | FileCheck --allow-empty --check-prefix=CHECK-NO-ATOMICS %s <%t
+
#include "test.h"
void *Thread(void *a) {
@@ -18,3 +27,5 @@ int main() {
}
// CHECK: WARNING: ThreadSanitizer: data race
+
+// CHECK-NO-ATOMICS-NOT: WARNING: ThreadSanitizer: data race
diff --git a/test/tsan/atomic_store.cc b/test/tsan/atomic_store.cc
new file mode 100644
index 0000000000000..7ff4879d3cae6
--- /dev/null
+++ b/test/tsan/atomic_store.cc
@@ -0,0 +1,49 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s
+#include "test.h"
+
+long long Data;
+long long Sync;
+
+void *Thread1(void *x) {
+ Data++;
+ __atomic_store_n(&Sync, 1, __ATOMIC_RELEASE);
+ barrier_wait(&barrier);
+ barrier_wait(&barrier);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ barrier_wait(&barrier);
+ if (__atomic_load_n(&Sync, __ATOMIC_RELAXED) != 1)
+ exit(0);
+ // This store must terminate release sequence of the store in Thread1,
+ // thus tsan must detect race between Thread1 and main on Data.
+ __atomic_store_n(&Sync, 2, __ATOMIC_RELEASE);
+ barrier_wait(&barrier);
+ return NULL;
+}
+
+int main() {
+ barrier_init(&barrier, 3);
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, NULL);
+ pthread_create(&t[1], NULL, Thread2, NULL);
+ barrier_wait(&barrier);
+ barrier_wait(&barrier);
+ if (__atomic_load_n(&Sync, __ATOMIC_ACQUIRE) != 2)
+ exit(0);
+ if (Data != 1)
+ exit(0);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+ fprintf(stderr, "DONE\n");
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Read
+// CHECK: #0 main
+// CHECK: Previous write
+// CHECK: #0 Thread1
+// CHECK: Location is global 'Data'
+// CHECK: DONE
diff --git a/test/tsan/debug_alloc_stack.cc b/test/tsan/debug_alloc_stack.cc
new file mode 100644
index 0000000000000..303c103206f8e
--- /dev/null
+++ b/test/tsan/debug_alloc_stack.cc
@@ -0,0 +1,84 @@
+// RUN: %clangxx_tsan -O0 %s -o %t
+// RUN: env %env_tsan_opts=stack_trace_format=DEFAULT %deflake %run %t 2>&1 | FileCheck %s
+
+// Until I figure out how to make this test work on Linux
+// REQUIRES: system-darwin
+
+#include "test.h"
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef __APPLE__
+#include <sys/types.h>
+#endif
+
+extern "C" int __tsan_get_alloc_stack(void *addr, void **trace, size_t size,
+ int *thread_id, void *os_id);
+
+char *mem;
+void alloc_func() { mem = (char *)malloc(10); }
+
+void *AllocThread(void *context) {
+ uint64_t tid;
+#ifdef __APPLE__
+ pthread_threadid_np(NULL, &tid);
+#else
+ tid = gettid();
+#endif
+ fprintf(stderr, "alloc stack thread os id = 0x%llx\n", tid);
+ // CHECK: alloc stack thread os id = [[THREAD_OS_ID:0x[0-9a-f]+]]
+ alloc_func();
+ return NULL;
+}
+
+void *RaceThread(void *context) {
+ *mem = 'a';
+ barrier_wait(&barrier);
+ return NULL;
+}
+
+int main() {
+ pthread_t t;
+ barrier_init(&barrier, 2);
+
+ pthread_create(&t, NULL, AllocThread, NULL);
+ pthread_join(t, NULL);
+
+ void *trace[100];
+ size_t num_frames = 100;
+ int thread_id;
+ void *thread_os_id;
+ num_frames =
+ __tsan_get_alloc_stack(mem, trace, num_frames, &thread_id, &thread_os_id);
+
+ fprintf(stderr, "alloc stack retval %s\n",
+ (num_frames > 0 && num_frames < 10) ? "ok" : "");
+ // CHECK: alloc stack retval ok
+ fprintf(stderr, "thread id = %d\n", thread_id);
+ // CHECK: thread id = 1
+ fprintf(stderr, "thread os id = 0x%llx\n", (uint64_t)thread_os_id);
+ // CHECK: thread os id = [[THREAD_OS_ID]]
+ fprintf(stderr, "%p\n", trace[0]);
+ // CHECK: [[ALLOC_FRAME_0:0x[0-9a-f]+]]
+ fprintf(stderr, "%p\n", trace[1]);
+ // CHECK: [[ALLOC_FRAME_1:0x[0-9a-f]+]]
+ fprintf(stderr, "%p\n", trace[2]);
+ // CHECK: [[ALLOC_FRAME_2:0x[0-9a-f]+]]
+
+ pthread_create(&t, NULL, RaceThread, NULL);
+ barrier_wait(&barrier);
+ mem[0] = 'b';
+ pthread_join(t, NULL);
+
+ free(mem);
+
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Location is heap block of size 10 at {{.*}} allocated by thread T1
+// CHECK: #0 [[ALLOC_FRAME_0]]
+// CHECK: #1 [[ALLOC_FRAME_1]] in alloc_func
+// CHECK: #2 [[ALLOC_FRAME_2]] in AllocThread
diff --git a/test/tsan/debug_locate.cc b/test/tsan/debug_locate.cc
new file mode 100644
index 0000000000000..01b0960d85b72
--- /dev/null
+++ b/test/tsan/debug_locate.cc
@@ -0,0 +1,43 @@
+// RUN: %clangxx_tsan -O0 %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern "C" const char *
+__tsan_locate_address(void *addr, char *name, size_t name_size,
+ void **region_address_ptr, size_t *region_size_ptr);
+
+long global_var;
+
+int main() {
+ long stack_var;
+ void *heap_var = malloc(10);
+
+ fprintf(stderr, "stack_var = %p\n", &stack_var);
+ fprintf(stderr, "global_var = %p\n", &global_var);
+ fprintf(stderr, "heap_var = %p\n", heap_var);
+ // CHECK: stack_var = [[STACK_VAR:0x[0-9a-f]+]]
+ // CHECK: global_var = [[GLOBAL_VAR:0x[0-9a-f]+]]
+ // CHECK: heap_var = [[HEAP_VAR:0x[0-9a-f]+]]
+
+ const char *type;
+ char name[128];
+ void *start;
+ size_t size;
+ type = __tsan_locate_address(&stack_var, name, 128, &start, &size);
+ fprintf(stderr, "type: %s\n", type);
+ // CHECK: type: stack
+
+ type = __tsan_locate_address(&global_var, name, 128, &start, &size);
+ fprintf(stderr, "type: %s, name = %s, start = %p, size = %zu\n", type, name,
+ start, size);
+ // CHECK: type: global, name = global_var, start = [[GLOBAL_VAR]], size = {{8|0}}
+
+ type = __tsan_locate_address(heap_var, name, 128, &start, &size);
+ fprintf(stderr, "type: %s, start = %p, size = %zu\n", type, start, size);
+ // CHECK: type: heap, start = [[HEAP_VAR]], size = 10
+
+ free(heap_var);
+ return 0;
+}
diff --git a/test/tsan/exceptions.cc b/test/tsan/exceptions.cc
new file mode 100644
index 0000000000000..193e115f78020
--- /dev/null
+++ b/test/tsan/exceptions.cc
@@ -0,0 +1,185 @@
+// RUN: %clangxx_tsan -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+
+#include "test.h"
+#include <setjmp.h>
+
+__attribute__((noinline)) void throws_int() {
+ throw 42;
+}
+
+__attribute__((noinline)) void callee_throws() {
+ try {
+ throws_int();
+ } catch (int) { // NOLINT
+ fprintf(stderr, "callee_throws caught exception\n");
+ }
+}
+
+__attribute__((noinline)) void throws_catches_rethrows() {
+ try {
+ throws_int();
+ } catch (int) { // NOLINT
+ fprintf(stderr, "throws_catches_rethrows caught exception\n");
+ throw;
+ }
+}
+
+__attribute__((noinline)) void callee_rethrows() {
+ try {
+ throws_catches_rethrows();
+ } catch (int) { // NOLINT
+ fprintf(stderr, "callee_rethrows caught exception\n");
+ }
+}
+
+__attribute__((noinline)) void throws_and_catches() {
+ try {
+ throws_int();
+ } catch (int) { // NOLINT
+ fprintf(stderr, "throws_and_catches caught exception\n");
+ }
+}
+
+__attribute__((noinline)) void nested_try() {
+ try {
+ try {
+ throws_int();
+ } catch (double) { // NOLINT
+ fprintf(stderr, "nested_try inner block caught exception\n");
+ }
+ } catch (int) { // NOLINT
+ fprintf(stderr, "nested_try outer block caught exception\n");
+ }
+}
+
+__attribute__((noinline)) void nested_try2() {
+ try {
+ try {
+ throws_int();
+ } catch (int) { // NOLINT
+ fprintf(stderr, "nested_try inner block caught exception\n");
+ }
+ } catch (double) { // NOLINT
+ fprintf(stderr, "nested_try outer block caught exception\n");
+ }
+}
+
+class ClassWithDestructor {
+ public:
+ ClassWithDestructor() {
+ fprintf(stderr, "ClassWithDestructor\n");
+ }
+ ~ClassWithDestructor() {
+ fprintf(stderr, "~ClassWithDestructor\n");
+ }
+};
+
+__attribute__((noinline)) void local_object_then_throw() {
+ ClassWithDestructor obj;
+ throws_int();
+}
+
+__attribute__((noinline)) void cpp_object_with_destructor() {
+ try {
+ local_object_then_throw();
+ } catch (int) { // NOLINT
+ fprintf(stderr, "cpp_object_with_destructor caught exception\n");
+ }
+}
+
+__attribute__((noinline)) void recursive_call(long n) {
+ if (n > 0) {
+ recursive_call(n - 1);
+ } else {
+ throws_int();
+ }
+}
+
+__attribute__((noinline)) void multiframe_unwind() {
+ try {
+ recursive_call(5);
+ } catch (int) { // NOLINT
+ fprintf(stderr, "multiframe_unwind caught exception\n");
+ }
+}
+
+__attribute__((noinline)) void longjmp_unwind() {
+ jmp_buf env;
+ int i = setjmp(env);
+ if (i != 0) {
+ fprintf(stderr, "longjmp_unwind jumped\n");
+ return;
+ }
+
+ try {
+ longjmp(env, 42);
+ } catch (int) { // NOLINT
+ fprintf(stderr, "longjmp_unwind caught exception\n");
+ }
+}
+
+__attribute__((noinline)) void recursive_call_longjmp(jmp_buf env, long n) {
+ if (n > 0) {
+ recursive_call_longjmp(env, n - 1);
+ } else {
+ longjmp(env, 42);
+ }
+}
+
+__attribute__((noinline)) void longjmp_unwind_multiple_frames() {
+ jmp_buf env;
+ int i = setjmp(env);
+ if (i != 0) {
+ fprintf(stderr, "longjmp_unwind_multiple_frames jumped\n");
+ return;
+ }
+
+ try {
+ recursive_call_longjmp(env, 5);
+ } catch (int) { // NOLINT
+ fprintf(stderr, "longjmp_unwind_multiple_frames caught exception\n");
+ }
+}
+
+#define CHECK_SHADOW_STACK(val) \
+ fprintf(stderr, (val == __tsan_testonly_shadow_stack_current_size() \
+ ? "OK.\n" \
+ : "Shadow stack leak!\n"));
+
+int main(int argc, const char * argv[]) {
+ fprintf(stderr, "Hello, World!\n");
+ unsigned long shadow_stack_size = __tsan_testonly_shadow_stack_current_size();
+
+ throws_and_catches();
+ CHECK_SHADOW_STACK(shadow_stack_size);
+
+ callee_throws();
+ CHECK_SHADOW_STACK(shadow_stack_size);
+
+ callee_rethrows();
+ CHECK_SHADOW_STACK(shadow_stack_size);
+
+ nested_try();
+ CHECK_SHADOW_STACK(shadow_stack_size);
+
+ nested_try2();
+ CHECK_SHADOW_STACK(shadow_stack_size);
+
+ cpp_object_with_destructor();
+ CHECK_SHADOW_STACK(shadow_stack_size);
+
+ multiframe_unwind();
+ CHECK_SHADOW_STACK(shadow_stack_size);
+
+ longjmp_unwind();
+ CHECK_SHADOW_STACK(shadow_stack_size);
+
+ longjmp_unwind_multiple_frames();
+ CHECK_SHADOW_STACK(shadow_stack_size);
+
+ return 0;
+}
+
+// CHECK: Hello, World!
+// CHECK-NOT: Shadow stack leak
diff --git a/test/tsan/fork_atexit.cc b/test/tsan/fork_atexit.cc
index 15cf0a2485ca4..6e3a2f5c4ba78 100644
--- a/test/tsan/fork_atexit.cc
+++ b/test/tsan/fork_atexit.cc
@@ -7,7 +7,7 @@
#include <sys/wait.h>
void foo() {
- printf("CHILD ATEXIT\n");
+ fprintf(stderr, "CHILD ATEXIT\n");
}
void *worker(void *unused) {
diff --git a/test/tsan/global_race.cc b/test/tsan/global_race.cc
index a35299619e9d9..ec26b06f5c1ca 100644
--- a/test/tsan/global_race.cc
+++ b/test/tsan/global_race.cc
@@ -1,4 +1,14 @@
-// RUN: %clangxx_tsan -O1 %s -o %T/global_race.cc.exe && %deflake %run %T/global_race.cc.exe | FileCheck %s
+// RUN: %clangxx_tsan -O1 %s -o %T/global_race.cc.exe && %deflake %run %T/global_race.cc.exe 2>&1 \
+// RUN: | FileCheck %s
+
+// Also check that memory access instrumentation can be configured by either
+// driver or legacy flags:
+
+// RUN: %clangxx_tsan -O1 %s -o %T/global_race.cc.exe -fno-sanitize-thread-memory-access && not %deflake %run %T/global_race.cc.exe 2>&1 \
+// RUN: | FileCheck --allow-empty --check-prefix=CHECK-MEMORY-ACCESS-OFF %s
+// RUN: %clangxx_tsan -O1 %s -o %T/global_race.cc.exe -mllvm -tsan-instrument-memory-accesses=0 && not %deflake %run %T/global_race.cc.exe 2>&1 \
+// RUN: | FileCheck --allow-empty --check-prefix=CHECK-MEMORY-ACCESS-OFF %s
+
#include "test.h"
int GlobalData[10];
@@ -23,3 +33,4 @@ int main() {
// CHECK: WARNING: ThreadSanitizer: data race
// CHECK: Location is global 'GlobalData' {{(of size 40 )?}}at [[ADDR]] (global_race.cc.exe+0x{{[0-9,a-f]+}})
+// CHECK-MEMORY-ACCESS-OFF-NOT: WARNING: ThreadSanitizer: data race
diff --git a/test/tsan/ignore_lib4.cc b/test/tsan/ignore_lib4.cc
index 193df11d2b2a7..84d8b2768a94d 100644
--- a/test/tsan/ignore_lib4.cc
+++ b/test/tsan/ignore_lib4.cc
@@ -3,8 +3,6 @@
// RUN: echo "called_from_lib:libignore_lib4.so" > %t.supp
// RUN: %env_tsan_opts=suppressions='%t.supp' %run %t 2>&1 | FileCheck %s
-// Longjmp assembly has not been implemented for mips64 yet
-// XFAIL: mips64
// powerpc64 big endian bots failed with "FileCheck error: '-' is empty" due
// to a segmentation fault.
// UNSUPPORTED: powerpc64-unknown-linux-gnu
diff --git a/test/tsan/ignore_lib5.cc b/test/tsan/ignore_lib5.cc
new file mode 100644
index 0000000000000..d7cd28500be91
--- /dev/null
+++ b/test/tsan/ignore_lib5.cc
@@ -0,0 +1,75 @@
+// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib1.so
+// RUN: %clangxx_tsan -O1 %s -o %t
+// RUN: echo running w/o suppressions:
+// RUN: %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOSUPP
+// RUN: echo running with suppressions:
+// RUN: %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP
+
+// REQUIRES: stable-runtime
+
+// Previously the test episodically failed with:
+// ThreadSanitizer: called_from_lib suppression '/libignore_lib1.so$' is
+// matched against 2 libraries: '/libignore_lib1.so' and '/libignore_lib1.so'
+// This was caused by non-atomicity of reading of /proc/self/maps.
+
+#ifndef LIB
+
+#include <dlfcn.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <libgen.h>
+#include <string>
+#include "test.h"
+
+#ifndef MAP_32BIT
+# define MAP_32BIT 0
+#endif
+
+#ifdef __APPLE__
+# define TSAN_MAP_ANON MAP_ANON
+#else
+# define TSAN_MAP_ANON MAP_ANONYMOUS
+#endif
+
+void *thr(void *arg) {
+ // This thread creates lots of separate mappings in /proc/self/maps before
+ // the ignored library.
+ for (int i = 0; i < 10000; i++) {
+ if (i == 5000)
+ barrier_wait(&barrier);
+ mmap(0, 4096, PROT_READ, TSAN_MAP_ANON | MAP_PRIVATE | MAP_32BIT, -1 , 0);
+ mmap(0, 4096, PROT_WRITE, TSAN_MAP_ANON | MAP_PRIVATE | MAP_32BIT, -1 , 0);
+ }
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ barrier_init(&barrier, 2);
+ pthread_t th;
+ pthread_create(&th, 0, thr, 0);
+ barrier_wait(&barrier);
+ std::string lib = std::string(dirname(argv[0])) + "/libignore_lib1.so";
+ void *h = dlopen(lib.c_str(), RTLD_GLOBAL | RTLD_NOW);
+ if (h == 0)
+ exit(printf("failed to load the library (%d)\n", errno));
+ void (*f)() = (void(*)())dlsym(h, "libfunc");
+ if (f == 0)
+ exit(printf("failed to find the func (%d)\n", errno));
+ pthread_join(th, 0);
+ f();
+}
+
+#else // #ifdef LIB
+
+#include "ignore_lib_lib.h"
+
+#endif // #ifdef LIB
+
+// CHECK-NOSUPP: WARNING: ThreadSanitizer: data race
+// CHECK-NOSUPP: OK
+
+// CHECK-WITHSUPP-NOT: WARNING: ThreadSanitizer: data race
+// CHECK-WITHSUPP: OK
+
diff --git a/test/tsan/ignore_lib5.cc.supp b/test/tsan/ignore_lib5.cc.supp
new file mode 100644
index 0000000000000..9f4119ec0bc47
--- /dev/null
+++ b/test/tsan/ignore_lib5.cc.supp
@@ -0,0 +1,2 @@
+called_from_lib:/libignore_lib1.so$
+
diff --git a/test/tsan/java.h b/test/tsan/java.h
index 565a7a7fdabff..e9aa4ee2440b1 100644
--- a/test/tsan/java.h
+++ b/test/tsan/java.h
@@ -7,6 +7,7 @@ void __tsan_java_init(jptr heap_begin, jptr heap_size);
int __tsan_java_fini();
void __tsan_java_alloc(jptr ptr, jptr size);
void __tsan_java_free(jptr ptr, jptr size);
+jptr __tsan_java_find(jptr *from_ptr, jptr to);
void __tsan_java_move(jptr src, jptr dst, jptr size);
void __tsan_java_finalize();
void __tsan_java_mutex_lock(jptr addr);
diff --git a/test/tsan/libcxx/lit.local.cfg b/test/tsan/libcxx/lit.local.cfg
index 202b44ee116d9..3ee705736e6fe 100644
--- a/test/tsan/libcxx/lit.local.cfg
+++ b/test/tsan/libcxx/lit.local.cfg
@@ -5,6 +5,8 @@ def getRoot(config):
root = getRoot(config)
-if not root.has_libcxx:
+# Only run if we have an instrumented libcxx. On Darwin, run always (we have
+# interceptors to support the system-provided libcxx).
+if not root.has_libcxx and root.host_os != 'Darwin':
config.unsupported = True
diff --git a/test/tsan/lit.cfg b/test/tsan/lit.cfg
index 1fc1eccd15ead..5d82cc9d4921c 100644
--- a/test/tsan/lit.cfg
+++ b/test/tsan/lit.cfg
@@ -38,13 +38,15 @@ if config.compiler_id == 'GNU':
else:
extra_cflags = []
+tsan_incdir = config.test_source_root + "/../"
# Setup default compiler flags used with -fsanitize=thread option.
clang_tsan_cflags = (["-fsanitize=thread",
"-Wall"] +
[config.target_cflags] +
config.debug_info_flags +
- extra_cflags)
-clang_tsan_cxxflags = config.cxx_mode_flags + clang_tsan_cflags
+ extra_cflags +
+ ["-I%s" % tsan_incdir])
+clang_tsan_cxxflags = config.cxx_mode_flags + clang_tsan_cflags + ["-std=c++11"] + ["-I%s" % tsan_incdir]
# Add additional flags if we're using instrumented libc++.
# Instrumented libcxx currently not supported on Darwin.
if config.has_libcxx and config.host_os != 'Darwin':
@@ -54,8 +56,7 @@ if config.has_libcxx and config.host_os != 'Darwin':
libcxx_incdir = os.path.join(libcxx_path, "include", "c++", "v1")
libcxx_libdir = os.path.join(libcxx_path, "lib")
libcxx_so = os.path.join(libcxx_libdir, "libc++.so")
- clang_tsan_cxxflags += ["-std=c++11",
- "-nostdinc++",
+ clang_tsan_cxxflags += ["-nostdinc++",
"-I%s" % libcxx_incdir,
libcxx_so,
"-Wl,-rpath=%s" % libcxx_libdir]
@@ -69,7 +70,7 @@ config.substitutions.append( ("%clangxx_tsan ", build_invocation(clang_tsan_cxxf
# Define CHECK-%os to check for OS-dependent output.
config.substitutions.append( ('CHECK-%os', ("CHECK-" + config.host_os)))
-config.substitutions.append( ("%deflake ", os.path.join(os.path.dirname(__file__), "deflake.bash")) )
+config.substitutions.append( ("%deflake ", os.path.join(os.path.dirname(__file__), "deflake.bash") + " "))
# Default test suffixes.
config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm']
diff --git a/test/tsan/longjmp.cc b/test/tsan/longjmp.cc
index 61d285c11bf2c..a8abca6017586 100644
--- a/test/tsan/longjmp.cc
+++ b/test/tsan/longjmp.cc
@@ -1,8 +1,5 @@
// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
-// Longjmp assembly has not been implemented for mips64 yet
-// XFAIL: mips64
-
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
diff --git a/test/tsan/longjmp2.cc b/test/tsan/longjmp2.cc
index 2b2775a8ca1e7..d396f3fec66e7 100644
--- a/test/tsan/longjmp2.cc
+++ b/test/tsan/longjmp2.cc
@@ -1,8 +1,5 @@
// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
-// Longjmp assembly has not been implemented for mips64 yet
-// XFAIL: mips64
-
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
diff --git a/test/tsan/longjmp3.cc b/test/tsan/longjmp3.cc
index 197b91e1cdc35..842cf264c977c 100644
--- a/test/tsan/longjmp3.cc
+++ b/test/tsan/longjmp3.cc
@@ -1,8 +1,5 @@
// RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s
-// Longjmp assembly has not been implemented for mips64 yet
-// XFAIL: mips64
-
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/test/tsan/longjmp4.cc b/test/tsan/longjmp4.cc
index 3785a0f072614..4c2fbf0c4028f 100644
--- a/test/tsan/longjmp4.cc
+++ b/test/tsan/longjmp4.cc
@@ -1,8 +1,5 @@
// RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s
-// Longjmp assembly has not been implemented for mips64 yet
-// XFAIL: mips64
-
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/test/tsan/map32bit.cc b/test/tsan/map32bit.cc
index 0411f29a9504e..3b4f8990016e8 100644
--- a/test/tsan/map32bit.cc
+++ b/test/tsan/map32bit.cc
@@ -8,7 +8,7 @@
// https://github.com/google/sanitizers/issues/412
// MAP_32BIT flag for mmap is supported only for x86_64.
-// XFAIL: mips64
+// XFAIL: mips
// XFAIL: aarch64
// XFAIL: powerpc64
diff --git a/test/tsan/pie_test.cc b/test/tsan/pie_test.cc
index 8635f9cd403fa..93d31daf5fd61 100644
--- a/test/tsan/pie_test.cc
+++ b/test/tsan/pie_test.cc
@@ -1,12 +1,6 @@
// Check if tsan work with PIE binaries.
// RUN: %clang_tsan %s -pie -fpic -o %t && %run %t
-// Some kernels might map PIE segments outside the current segment
-// mapping defined for x86 [1].
-// [1] https://git.kernel.org/linus/d1fd836dcf00d2028c700c7e44d2c23404062c90
-
-// UNSUPPORTED: x86
-
int main(void) {
return 0;
}
diff --git a/test/tsan/signal_block.cc b/test/tsan/signal_block.cc
new file mode 100644
index 0000000000000..dfd4259c43c9b
--- /dev/null
+++ b/test/tsan/signal_block.cc
@@ -0,0 +1,60 @@
+// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+
+// Test that a signal is not delivered when it is blocked.
+
+#include "test.h"
+#include <semaphore.h>
+#include <signal.h>
+#include <errno.h>
+
+int stop;
+sig_atomic_t signal_blocked;
+
+void handler(int signum) {
+ if (signal_blocked) {
+ fprintf(stderr, "signal arrived when blocked\n");
+ exit(1);
+ }
+}
+
+void *thread(void *arg) {
+ sigset_t myset;
+ sigemptyset(&myset);
+ sigaddset(&myset, SIGUSR1);
+ while (!__atomic_load_n(&stop, __ATOMIC_RELAXED)) {
+ usleep(1);
+ if (pthread_sigmask(SIG_BLOCK, &myset, 0)) {
+ fprintf(stderr, "pthread_sigmask failed %d\n", errno);
+ exit(1);
+ }
+ signal_blocked = 1;
+ usleep(1);
+ signal_blocked = 0;
+ if (pthread_sigmask(SIG_UNBLOCK, &myset, 0)) {
+ fprintf(stderr, "pthread_sigmask failed %d\n", errno);
+ exit(1);
+ }
+ }
+ return 0;
+}
+
+int main(int argc, char** argv) {
+ struct sigaction act = {};
+ act.sa_handler = &handler;
+ if (sigaction(SIGUSR1, &act, 0)) {
+ fprintf(stderr, "sigaction failed %d\n", errno);
+ return 1;
+ }
+ pthread_t th;
+ pthread_create(&th, 0, thread, 0);
+ for (int i = 0; i < 100000; i++)
+ pthread_kill(th, SIGUSR1);
+ __atomic_store_n(&stop, 1, __ATOMIC_RELAXED);
+ pthread_join(th, 0);
+ fprintf(stderr, "DONE\n");
+ return 0;
+}
+
+// CHECK-NOT: ThreadSanitizer CHECK
+// CHECK-NOT: WARNING: ThreadSanitizer:
+// CHECK: DONE
diff --git a/test/tsan/signal_cond.cc b/test/tsan/signal_cond.cc
index beb2e0266e508..6c20dd8f2e394 100644
--- a/test/tsan/signal_cond.cc
+++ b/test/tsan/signal_cond.cc
@@ -14,7 +14,7 @@ pthread_cond_t cond;
void sig_handler(int sig) {
(void)sig;
- write(1, "SIGNAL\n", sizeof("SIGNAL\n") - 1);
+ write(2, "SIGNAL\n", sizeof("SIGNAL\n") - 1);
barrier_wait(&barrier);
}
diff --git a/test/tsan/signal_longjmp.cc b/test/tsan/signal_longjmp.cc
index 45e24626cbfab..f9fa4f54f507d 100644
--- a/test/tsan/signal_longjmp.cc
+++ b/test/tsan/signal_longjmp.cc
@@ -3,8 +3,6 @@
// Test case for longjumping out of signal handler:
// https://github.com/google/sanitizers/issues/482
-// Longjmp assembly has not been implemented for mips64 yet
-// XFAIL: mips64
// This test fails on powerpc64 BE (VMA=44), a segmentation fault
// error happens at the second assignment
// "((volatile int *volatile)mem)[1] = 1".
diff --git a/test/tsan/simple_stack.c b/test/tsan/simple_stack.c
index 6ef92fb46c683..71a3911b39bee 100644
--- a/test/tsan/simple_stack.c
+++ b/test/tsan/simple_stack.c
@@ -1,4 +1,3 @@
-// RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
#include "test.h"
int Global;
@@ -47,20 +46,40 @@ int main() {
return 0;
}
+// RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s
+
+// Also check that functions instrumentation can be configured by either driver
+// or legacy flags:
+
+// RUN: %clangxx_tsan -O1 %s -o %t -fno-sanitize-thread-func-entry-exit && %deflake %run %t 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-FUNC-ENTRY-EXIT-OFF %s
+// RUN: %clangxx_tsan -O1 %s -o %t -mllvm -tsan-instrument-func-entry-exit=0 && %deflake %run %t 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-FUNC-ENTRY-EXIT-OFF %s
+
// CHECK: WARNING: ThreadSanitizer: data race
// CHECK-NEXT: Write of size 4 at {{.*}} by thread T1:
-// CHECK-NEXT: #0 foo1{{.*}} {{.*}}simple_stack.c:7{{(:10)?}} ({{.*}})
-// CHECK-NEXT: #1 bar1{{.*}} {{.*}}simple_stack.c:12{{(:3)?}} ({{.*}})
-// CHECK-NEXT: #2 Thread1{{.*}} {{.*}}simple_stack.c:26{{(:3)?}} ({{.*}})
+// CHECK-NEXT: #0 foo1{{.*}} {{.*}}simple_stack.c:6{{(:10)?}} ({{.*}})
+// CHECK-NEXT: #1 bar1{{.*}} {{.*}}simple_stack.c:11{{(:3)?}} ({{.*}})
+// CHECK-NEXT: #2 Thread1{{.*}} {{.*}}simple_stack.c:25{{(:3)?}} ({{.*}})
// CHECK: Previous read of size 4 at {{.*}} by thread T2:
-// CHECK-NEXT: #0 foo2{{.*}} {{.*}}simple_stack.c:16{{(:20)?}} ({{.*}})
-// CHECK-NEXT: #1 bar2{{.*}} {{.*}}simple_stack.c:21{{(:3)?}} ({{.*}})
-// CHECK-NEXT: #2 Thread2{{.*}} {{.*}}simple_stack.c:31{{(:3)?}} ({{.*}})
+// CHECK-NEXT: #0 foo2{{.*}} {{.*}}simple_stack.c:15{{(:20)?}} ({{.*}})
+// CHECK-NEXT: #1 bar2{{.*}} {{.*}}simple_stack.c:20{{(:3)?}} ({{.*}})
+// CHECK-NEXT: #2 Thread2{{.*}} {{.*}}simple_stack.c:30{{(:3)?}} ({{.*}})
// CHECK: Thread T1 (tid={{.*}}, running) created by main thread at:
// CHECK-NEXT: #0 pthread_create {{.*}} ({{.*}})
-// CHECK-NEXT: #1 StartThread{{.*}} {{.*}}simple_stack.c:37{{(:3)?}} ({{.*}})
-// CHECK-NEXT: #2 main{{.*}} {{.*}}simple_stack.c:43{{(:3)?}} ({{.*}})
+// CHECK-NEXT: #1 StartThread{{.*}} {{.*}}simple_stack.c:36{{(:3)?}} ({{.*}})
+// CHECK-NEXT: #2 main{{.*}} {{.*}}simple_stack.c:42{{(:3)?}} ({{.*}})
// CHECK: Thread T2 ({{.*}}) created by main thread at:
// CHECK-NEXT: #0 pthread_create {{.*}} ({{.*}})
-// CHECK-NEXT: #1 StartThread{{.*}} {{.*}}simple_stack.c:37{{(:3)?}} ({{.*}})
-// CHECK-NEXT: #2 main{{.*}} {{.*}}simple_stack.c:44{{(:3)?}} ({{.*}})
+// CHECK-NEXT: #1 StartThread{{.*}} {{.*}}simple_stack.c:36{{(:3)?}} ({{.*}})
+// CHECK-NEXT: #2 main{{.*}} {{.*}}simple_stack.c:43{{(:3)?}} ({{.*}})
+
+// CHECK-FUNC-ENTRY-EXIT-OFF: WARNING: ThreadSanitizer: data race
+// CHECK-FUNC-ENTRY-EXIT-OFF-NEXT: Write of size 4 at {{.*}} by thread T1:
+// CHECK-FUNC-ENTRY-EXIT-OFF-NEXT: #0 foo1{{.*}} {{.*}}simple_stack.c:6{{(:10)?}} ({{.*}})
+// CHECK-FUNC-ENTRY-EXIT-OFF: Previous read of size 4 at {{.*}} by thread T2:
+// CHECK-FUNC-ENTRY-EXIT-OFF-NEXT: #0 foo2{{.*}} {{.*}}simple_stack.c:15{{(:20)?}} ({{.*}})
+// CHECK-FUNC-ENTRY-EXIT-OFF: Thread T1 (tid={{.*}}, running) created by main thread at:
+// CHECK-FUNC-ENTRY-EXIT-OFF-NEXT: #0 pthread_create {{.*}} ({{.*}})
+// CHECK-FUNC-ENTRY-EXIT-OFF: Thread T2 ({{.*}}) created by main thread at:
+// CHECK-FUNC-ENTRY-EXIT-OFF-NEXT: #0 pthread_create {{.*}} ({{.*}})
diff --git a/test/tsan/test.h b/test/tsan/test.h
index e3affdc0837d0..6b981c09f53df 100644
--- a/test/tsan/test.h
+++ b/test/tsan/test.h
@@ -6,6 +6,7 @@
#include <stddef.h>
#include <sched.h>
#include <stdarg.h>
+#include "sanitizer_common/print_address.h"
#ifdef __APPLE__
#include <mach/mach_time.h>
@@ -22,6 +23,7 @@ extern "C" {
void __tsan_testonly_barrier_init(invisible_barrier_t *barrier,
unsigned count);
void __tsan_testonly_barrier_wait(invisible_barrier_t *barrier);
+unsigned long __tsan_testonly_shadow_stack_current_size();
#ifdef __cplusplus
}
#endif
@@ -37,23 +39,6 @@ static inline void barrier_wait(invisible_barrier_t *barrier) {
// Default instance of the barrier, but a test can declare more manually.
invisible_barrier_t barrier;
-void print_address(const char *str, int n, ...) {
- fprintf(stderr, "%s", str);
- va_list ap;
- va_start(ap, n);
- while (n--) {
- void *p = va_arg(ap, void *);
-#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__)
- // On FreeBSD, the %p conversion specifier works as 0x%x and thus does not
- // match to the format used in the diagnotic message.
- fprintf(stderr, "0x%012lx ", (unsigned long) p);
-#elif defined(__mips64)
- fprintf(stderr, "0x%010lx ", (unsigned long) p);
-#endif
- }
- fprintf(stderr, "\n");
-}
-
#ifdef __APPLE__
unsigned long long monotonic_clock_ns() {
static mach_timebase_info_data_t timebase_info;
diff --git a/test/ubsan/CMakeLists.txt b/test/ubsan/CMakeLists.txt
index 7b14a70b76fa2..f4b73e87f56bb 100644
--- a/test/ubsan/CMakeLists.txt
+++ b/test/ubsan/CMakeLists.txt
@@ -22,13 +22,7 @@ endif()
foreach(arch ${UBSAN_TEST_ARCH})
set(UBSAN_TEST_TARGET_ARCH ${arch})
- if(${arch} MATCHES "arm|aarch64")
- # This is only true if we're cross-compiling.
- set(UBSAN_TEST_TARGET_CFLAGS ${COMPILER_RT_TEST_COMPILER_CFLAGS})
- else()
- get_target_flags_for_arch(${arch} UBSAN_TEST_TARGET_CFLAGS)
- string(REPLACE ";" " " UBSAN_TEST_TARGET_CFLAGS "${UBSAN_TEST_TARGET_CFLAGS}")
- endif()
+ get_test_cc_for_arch(${arch} UBSAN_TEST_TARGET_CC UBSAN_TEST_TARGET_CFLAGS)
add_ubsan_testsuite("Standalone" ubsan ${arch})
if(COMPILER_RT_HAS_ASAN AND ";${ASAN_SUPPORTED_ARCH};" MATCHES ";${arch};")
diff --git a/test/ubsan/TestCases/TypeCheck/null.cpp b/test/ubsan/TestCases/TypeCheck/null.cpp
index b1cba83d17db2..636fab82fd935 100644
--- a/test/ubsan/TestCases/TypeCheck/null.cpp
+++ b/test/ubsan/TestCases/TypeCheck/null.cpp
@@ -1,20 +1,34 @@
-// RUN: %clangxx -fsanitize=null %s -O3 -o %t
-// RUN: %run %t l 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD
-// RUN: %expect_crash %run %t s 2>&1 | FileCheck %s --check-prefix=CHECK-STORE
-// RUN: %run %t r 2>&1 | FileCheck %s --check-prefix=CHECK-REFERENCE
-// RUN: %run %t m 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER
-// RUN: %run %t f 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN
+// RUN: %clangxx -fsanitize=null -fno-sanitize-recover=null %s -O3 -o %t
+// RUN: not %run %t l 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD
+// RUN: not %run %t s 2>&1 | FileCheck %s --check-prefix=CHECK-STORE
+// RUN: not %run %t r 2>&1 | FileCheck %s --check-prefix=CHECK-REFERENCE
+// RUN: not %run %t m 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER
+// RUN: not %run %t f 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN
+// RUN: not %run %t t 2>&1 | FileCheck %s --check-prefix=CHECK-VCALL
+// RUN: not %run %t u 2>&1 | FileCheck %s --check-prefix=CHECK-VCALL2
struct S {
int f() { return 0; }
int k;
};
+struct T {
+ virtual int v() { return 1; }
+};
+
+struct U : T {
+ virtual int v() { return 2; }
+};
+
int main(int, char **argv) {
int *p = 0;
S *s = 0;
+ T *t = 0;
+ U *u = 0;
(void)*p; // ok!
+ (void)*t; // ok!
+ (void)*u; // ok!
switch (argv[1][0]) {
case 'l':
@@ -34,5 +48,11 @@ int main(int, char **argv) {
case 'f':
// CHECK-MEMFUN: null.cpp:[[@LINE+1]]:15: runtime error: member call on null pointer of type 'S'
return s->f();
+ case 't':
+ // CHECK-VCALL: null.cpp:[[@LINE+1]]:15: runtime error: member call on null pointer of type 'T'
+ return t->v();
+ case 'u':
+ // CHECK-VCALL2: null.cpp:[[@LINE+1]]:15: runtime error: member call on null pointer of type 'U'
+ return u->v();
}
}
diff --git a/test/ubsan/TestCases/TypeCheck/vptr.cpp b/test/ubsan/TestCases/TypeCheck/vptr.cpp
index 86b646da7561c..53a79c9fc7ee3 100644
--- a/test/ubsan/TestCases/TypeCheck/vptr.cpp
+++ b/test/ubsan/TestCases/TypeCheck/vptr.cpp
@@ -1,4 +1,4 @@
-// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t
+// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t -mllvm -enable-tail-merge=false
// RUN: %run %t rT && %run %t mT && %run %t fT && %run %t cT
// RUN: %run %t rU && %run %t mU && %run %t fU && %run %t cU
// RUN: %run %t rS && %run %t rV && %run %t oV
@@ -50,6 +50,8 @@ struct V : S {};
// Make p global so that lsan does not complain.
T *p = 0;
+volatile void *sink1, *sink2;
+
int access_p(T *p, char type);
int main(int argc, char **argv) {
@@ -74,6 +76,11 @@ int main(int argc, char **argv) {
char Buffer[sizeof(U)] = {};
char TStorage[sizeof(T)];
+ // Allocate two dummy objects so that the real object
+ // is not on the boundary of mapped memory. Otherwise ubsan
+ // will not be able to describe the vptr in detail.
+ sink1 = new T;
+ sink2 = new U;
switch (argv[1][1]) {
case '0':
p = reinterpret_cast<T*>(Buffer);
diff --git a/test/xray/CMakeLists.txt b/test/xray/CMakeLists.txt
new file mode 100644
index 0000000000000..50f6926bbe1e5
--- /dev/null
+++ b/test/xray/CMakeLists.txt
@@ -0,0 +1,48 @@
+set(XRAY_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+
+set(XRAY_TESTSUITES)
+set(XRAY_FDR_TESTSUITES)
+
+set(XRAY_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+set(XRAY_FDR_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+
+if(NOT COMPILER_RT_STANDALONE_BUILD AND COMPILER_RT_BUILD_XRAY AND
+ COMPILER_RT_HAS_XRAY)
+ list(APPEND XRAY_TEST_DEPS xray)
+ list(APPEND XRAY_FDR_TEST_DEPS xray-fdr)
+endif()
+
+set(XRAY_TEST_ARCH ${XRAY_SUPPORTED_ARCH})
+if (COMPILER_RT_BUILD_XRAY AND COMPILER_RT_HAS_XRAY)
+ foreach(arch ${XRAY_TEST_ARCH})
+ set(XRAY_TEST_TARGET_ARCH ${arch})
+ string(TOLOWER "-${arch}-${OS_NAME}" XRAY_TEST_CONFIG_SUFFIX)
+ get_test_cc_for_arch(${arch} XRAY_TEST_TARGET_CC XRAY_TEST_TARGET_CFLAGS)
+ string(TOUPPER ${arch} ARCH_UPPER_CASE)
+ set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
+
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
+ list(APPEND XRAY_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+ endforeach()
+
+ # Add unit tests.
+ 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)
+ list(APPEND XRAY_TEST_DEPS XRayUnitTests)
+ list(APPEND XRAY_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit)
+ endif()
+endif()
+
+add_lit_testsuite(check-xray "Running the XRay tests"
+ ${XRAY_TESTSUITES}
+ DEPENDS ${XRAY_TEST_DEPS})
+set_target_properties(check-xray PROPERTIES FOLDER "Compiler-RT Misc")
+
+add_lit_testsuite(check-xray-fdr "Running the XRay flight data recorder tests"
+ ${XRAY_FDR_TESTSUITES}
+ DEPENDS ${XRAY_FDR_TEST_DEPS})
+set_target_properties(check-xray-fdr PROPERTIES FOLDER "Compiler-RT Misc")
diff --git a/test/xray/TestCases/Linux/fixedsize-logging.cc b/test/xray/TestCases/Linux/fixedsize-logging.cc
new file mode 100644
index 0000000000000..90e766876c546
--- /dev/null
+++ b/test/xray/TestCases/Linux/fixedsize-logging.cc
@@ -0,0 +1,20 @@
+// Check to make sure that we have a log file with a fixed-size.
+
+// RUN: %clangxx_xray -std=c++11 %s -o %t
+// RUN: XRAY_OPTIONS="verbosity=1 xray_logfile_base=fixedsize-logging-" %run %t 2>&1 | FileCheck %s
+//
+// After all that, clean up the output xray log.
+//
+// RUN: rm fixedsize-logging-*
+
+#include <cstdio>
+
+[[clang::xray_always_instrument]] void foo() {
+ printf("foo() is always instrumented!");
+}
+
+int main() {
+ // CHECK: XRay: Log file in 'fixedsize-logging-{{.*}}'
+ foo();
+ // CHECK: foo() is always instrumented!
+}
diff --git a/test/xray/TestCases/Linux/optional-inmemory-log.cc b/test/xray/TestCases/Linux/optional-inmemory-log.cc
new file mode 100644
index 0000000000000..ef2c43f3be776
--- /dev/null
+++ b/test/xray/TestCases/Linux/optional-inmemory-log.cc
@@ -0,0 +1,21 @@
+// Make sure that we don't get the inmemory logging implementation enabled when
+// we turn it off via options.
+
+// RUN: %clangxx_xray -std=c++11 %s -o %t
+// RUN: XRAY_OPTIONS="verbosity=1 xray_naive_log=false xray_logfile_base=optional-inmemory-log.xray-" %run %t 2>&1 | FileCheck %s
+//
+// Make sure we clean out the logs in case there was a bug.
+//
+// RUN: rm -f optional-inmemory-log.xray-*
+
+#include <cstdio>
+
+[[clang::xray_always_instrument]] void foo() {
+ printf("foo() is always instrumented!");
+}
+
+int main() {
+ // CHECK-NOT: XRay: Log file in 'optional-inmemory-log.xray-{{.*}}'
+ foo();
+ // CHECK: foo() is always instrumented!
+}
diff --git a/test/xray/TestCases/Linux/patching-unpatching.cc b/test/xray/TestCases/Linux/patching-unpatching.cc
new file mode 100644
index 0000000000000..e684e427f068f
--- /dev/null
+++ b/test/xray/TestCases/Linux/patching-unpatching.cc
@@ -0,0 +1,48 @@
+// Check that we can patch and un-patch on demand, and that logging gets invoked
+// appropriately.
+//
+// RUN: %clangxx_xray -fxray-instrument -std=c++11 %s -o %t
+// RUN: XRAY_OPTIONS="patch_premain=false" %run %t 2>&1 | FileCheck %s
+// REQUIRES: stable-runtime
+
+#include "xray/xray_interface.h"
+
+#include <cstdio>
+
+bool called = false;
+
+void test_handler(int32_t fid, XRayEntryType type) {
+ printf("called: %d, type=%d\n", fid, static_cast<int32_t>(type));
+ called = true;
+}
+
+[[clang::xray_always_instrument]] void always_instrument() {
+ printf("always instrumented called\n");
+}
+
+int main() {
+ __xray_set_handler(test_handler);
+ always_instrument();
+ // CHECK: always instrumented called
+ auto status = __xray_patch();
+ printf("patching status: %d\n", static_cast<int32_t>(status));
+ // CHECK-NEXT: patching status: 1
+ always_instrument();
+ // CHECK-NEXT: called: {{.*}}, type=0
+ // CHECK-NEXT: always instrumented called
+ // CHECK-NEXT: called: {{.*}}, type=1
+ status = __xray_unpatch();
+ printf("patching status: %d\n", static_cast<int32_t>(status));
+ // CHECK-NEXT: patching status: 1
+ always_instrument();
+ // CHECK-NEXT: always instrumented called
+ status = __xray_patch();
+ printf("patching status: %d\n", static_cast<int32_t>(status));
+ // CHECK-NEXT: patching status: 1
+ __xray_remove_handler();
+ always_instrument();
+ // CHECK-NEXT: always instrumented called
+ status = __xray_unpatch();
+ printf("patching status: %d\n", static_cast<int32_t>(status));
+ // CHECK-NEXT: patching status: 1
+}
diff --git a/test/xray/Unit/lit.site.cfg.in b/test/xray/Unit/lit.site.cfg.in
new file mode 100644
index 0000000000000..1ebc7b9ec5f3f
--- /dev/null
+++ b/test/xray/Unit/lit.site.cfg.in
@@ -0,0 +1,12 @@
+@LIT_SITE_CFG_IN_HEADER@
+
+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")
+
+# Setup config name.
+config.name = 'XRay-Unit'
+
+config.test_exec_root = "@COMPILER_RT_BINARY_DIR@/lib/xray/tests"
+config.test_source_root = config.test_exec_root
diff --git a/test/xray/lit.cfg b/test/xray/lit.cfg
new file mode 100644
index 0000000000000..5d030e101452f
--- /dev/null
+++ b/test/xray/lit.cfg
@@ -0,0 +1,39 @@
+# -*- Python -*-
+
+import os
+
+# Setup config name.
+config.name = 'XRay' + config.name_suffix
+
+# Setup source root.
+config.test_source_root = os.path.dirname(__file__)
+
+# Setup default compiler flags use with -fxray-instrument option.
+clang_xray_cflags = (['-fxray-instrument', config.target_cflags])
+clang_xray_cxxflags = config.cxx_mode_flags + clang_xray_cflags
+
+
+def build_invocation(compile_flags):
+ return ' ' + ' '.join([config.clang] + compile_flags) + ' '
+
+# Setup substitutions.
+config.substitutions.append(
+ ('%clang ', build_invocation([config.target_cflags])))
+config.substitutions.append(
+ ('%clangxx ',
+ build_invocation(config.cxx_mode_flags + [config.target_cflags])))
+config.substitutions.append(
+ ('%clang_xray ', build_invocation(clang_xray_cflags)))
+config.substitutions.append(
+ ('%clangxx_xray', build_invocation(clang_xray_cxxflags)))
+
+# Default test suffixes.
+config.suffixes = ['.c', '.cc', '.cpp']
+
+if config.host_os not in ['Linux'] or config.host_arch.find('64') == -1:
+ config.unsupported = True
+
+# Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL
+# e.g. because the test sometimes passes, sometimes fails.
+if config.target_arch != 'aarch64':
+ config.available_features.add('stable-runtime')
diff --git a/test/xray/lit.site.cfg.in b/test/xray/lit.site.cfg.in
new file mode 100644
index 0000000000000..ee0ffcad4d9c8
--- /dev/null
+++ b/test/xray/lit.site.cfg.in
@@ -0,0 +1,13 @@
+@LIT_SITE_CFG_IN_HEADER@
+
+# Tool-specific config options.
+config.name_suffix = "@XRAY_TEST_CONFIG_SUFFIX@"
+config.xray_lit_source_dir = "@XRAY_LIT_SOURCE_DIR@"
+config.target_cflags = "@XRAY_TEST_TARGET_CFLAGS@"
+config.target_arch = "@XRAY_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")
+
+# Load tool-specific config that would do the real work.
+lit_config.load_config(config, "@XRAY_LIT_SOURCE_DIR@/lit.cfg")