aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPirama Arumuga Nainar <pirama@google.com>2015-04-10 21:22:52 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-04-10 21:23:02 +0000
commit3d7bf861dbf6f15644b7afa060a02557e3ff8855 (patch)
treeffba1da06cea1fd707cfad245b93280a7df99700
parent82f9cb33b564a9d72f09b478aabb44c4a83344c8 (diff)
parent7c9150579ed0278492f51cc8434b1d63a44b9bd1 (diff)
downloadcompiler-rt-3d7bf861dbf6f15644b7afa060a02557e3ff8855.tar.gz
Merge "Update aosp/master compiler-rt for rebase to r233350"
-rw-r--r--CMakeLists.txt13
-rw-r--r--LICENSE.TXT4
-rw-r--r--SDKs/README.txt9
-rw-r--r--SDKs/linux/README.txt2
-rw-r--r--SDKs/linux/usr/include/endian.h29
-rw-r--r--SDKs/linux/usr/include/fcntl.h17
-rw-r--r--SDKs/linux/usr/include/limits.h23
-rw-r--r--SDKs/linux/usr/include/stdio.h44
-rw-r--r--SDKs/linux/usr/include/stdlib.h36
-rw-r--r--SDKs/linux/usr/include/string.h31
-rw-r--r--SDKs/linux/usr/include/sys/fcntl.h29
-rw-r--r--SDKs/linux/usr/include/sys/mman.h47
-rw-r--r--SDKs/linux/usr/include/sys/stat.h24
-rw-r--r--SDKs/linux/usr/include/sys/types.h20
-rw-r--r--SDKs/linux/usr/include/unistd.h26
-rw-r--r--cmake/Modules/CompilerRTCompile.cmake36
-rw-r--r--cmake/config-ix.cmake22
-rw-r--r--include/sanitizer/coverage_interface.h17
-rw-r--r--lib/CMakeLists.txt5
-rw-r--r--lib/asan/Android.mk1
-rw-r--r--lib/asan/CMakeLists.txt8
-rw-r--r--lib/asan/asan_globals.cc14
-rw-r--r--lib/asan/asan_interceptors.cc79
-rw-r--r--lib/asan/asan_interceptors.h12
-rw-r--r--lib/asan/asan_interface_internal.h17
-rw-r--r--lib/asan/asan_internal.h16
-rw-r--r--lib/asan/asan_linux.cc74
-rw-r--r--lib/asan/asan_mac.cc14
-rw-r--r--lib/asan/asan_poisoning.cc6
-rw-r--r--lib/asan/asan_posix.cc7
-rw-r--r--lib/asan/asan_report.cc11
-rw-r--r--lib/asan/asan_rtl.cc119
-rw-r--r--lib/asan/asan_suppressions.cc10
-rw-r--r--lib/asan/asan_win.cc123
-rw-r--r--lib/asan/asan_win_dll_thunk.cc2
-rw-r--r--lib/asan/asan_win_dynamic_runtime_thunk.cc94
-rwxr-xr-xlib/asan/scripts/asan_symbolize.py3
-rw-r--r--lib/asan/tests/asan_asm_test.cc4
-rw-r--r--lib/asan/tests/asan_test.cc28
-rw-r--r--lib/builtins/clear_cache.c11
-rw-r--r--lib/builtins/fixdfdi.c41
-rw-r--r--lib/builtins/fixdfsi.c56
-rw-r--r--lib/builtins/fixdfti.c33
-rw-r--r--lib/builtins/fixsfdi.c38
-rw-r--r--lib/builtins/fixsfsi.c53
-rw-r--r--lib/builtins/fixsfti.c33
-rw-r--r--lib/builtins/fixtfdi.c23
-rw-r--r--lib/builtins/fixtfsi.c23
-rw-r--r--lib/builtins/fixtfti.c23
-rw-r--r--lib/builtins/fixunsdfdi.c38
-rw-r--r--lib/builtins/fixunsdfsi.c35
-rw-r--r--lib/builtins/fixunsdfti.c36
-rw-r--r--lib/builtins/fixunssfdi.c35
-rw-r--r--lib/builtins/fixunssfsi.c32
-rw-r--r--lib/builtins/fixunssfti.c37
-rw-r--r--lib/builtins/fixunstfdi.c22
-rw-r--r--lib/builtins/fixunstfsi.c22
-rw-r--r--lib/builtins/fixunstfti.c22
-rw-r--r--lib/builtins/fixunsxfdi.c2
-rw-r--r--lib/builtins/fixunsxfsi.c3
-rw-r--r--lib/builtins/fixunsxfti.c5
-rw-r--r--lib/builtins/fixxfdi.c6
-rw-r--r--lib/builtins/fixxfti.c8
-rw-r--r--lib/builtins/fp_fixint_impl.inc41
-rw-r--r--lib/builtins/fp_fixuint_impl.inc39
-rw-r--r--lib/dfsan/dfsan.cc2
-rw-r--r--lib/interception/interception.h1
-rw-r--r--lib/interception/interception_win.cc13
-rw-r--r--lib/lsan/lsan_common.cc10
-rw-r--r--lib/msan/tests/CMakeLists.txt1
-rw-r--r--lib/profile/InstrProfilingFile.c2
-rw-r--r--lib/sanitizer_common/CMakeLists.txt11
-rw-r--r--lib/sanitizer_common/sanitizer_common.cc29
-rw-r--r--lib/sanitizer_common/sanitizer_common.h42
-rw-r--r--lib/sanitizer_common/sanitizer_common_libcdep.cc22
-rw-r--r--lib/sanitizer_common/sanitizer_coverage_libcdep.cc410
-rw-r--r--lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc2
-rw-r--r--lib/sanitizer_common/sanitizer_flags.inc7
-rw-r--r--lib/sanitizer_common/sanitizer_linux.cc85
-rw-r--r--lib/sanitizer_common/sanitizer_linux.h2
-rw-r--r--lib/sanitizer_common/sanitizer_linux_libcdep.cc2
-rw-r--r--lib/sanitizer_common/sanitizer_mac.cc35
-rw-r--r--lib/sanitizer_common/sanitizer_posix.cc40
-rw-r--r--lib/sanitizer_common/sanitizer_stoptheworld.h3
-rw-r--r--lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc91
-rw-r--r--lib/sanitizer_common/sanitizer_suppressions.cc36
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer.cc88
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer.h110
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_internal.h109
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc74
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h11
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc52
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_mac.cc151
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_mac.h48
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc584
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc228
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_win.cc250
-rw-r--r--lib/sanitizer_common/sanitizer_symbolizer_win.h31
-rw-r--r--lib/sanitizer_common/sanitizer_win.cc32
-rwxr-xr-xlib/sanitizer_common/scripts/check_lint.sh4
-rwxr-xr-xlib/sanitizer_common/scripts/sancov.py78
-rw-r--r--lib/sanitizer_common/tests/CMakeLists.txt1
-rw-r--r--lib/sanitizer_common/tests/sanitizer_libc_test.cc6
-rw-r--r--lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc22
-rw-r--r--lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc10
-rw-r--r--lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc58
-rw-r--r--lib/tsan/Makefile.old4
-rw-r--r--lib/tsan/rtl/Makefile.old1
-rw-r--r--lib/tsan/rtl/tsan_interceptors.cc51
-rw-r--r--lib/tsan/rtl/tsan_report.cc6
-rw-r--r--lib/tsan/rtl/tsan_rtl.cc4
-rw-r--r--lib/tsan/rtl/tsan_rtl.h5
-rw-r--r--lib/tsan/rtl/tsan_rtl_thread.cc1
-rw-r--r--lib/tsan/rtl/tsan_suppressions.cc2
-rw-r--r--lib/tsan/rtl/tsan_sync.cc62
-rw-r--r--lib/tsan/rtl/tsan_sync.h3
-rw-r--r--lib/ubsan/CMakeLists.txt55
-rw-r--r--lib/ubsan/ubsan_diag.cc13
-rw-r--r--lib/ubsan/ubsan_flags.cc4
-rw-r--r--lib/ubsan/ubsan_handlers.cc4
-rw-r--r--lib/ubsan/ubsan_handlers_cxx.cc4
-rw-r--r--lib/ubsan/ubsan_init.cc4
-rw-r--r--lib/ubsan/ubsan_platform.h26
-rw-r--r--lib/ubsan/ubsan_type_hash.cc4
-rw-r--r--lib/ubsan/ubsan_value.cc4
-rw-r--r--lib/ubsan/ubsan_value.h7
-rw-r--r--make/platform/clang_darwin.mk78
-rw-r--r--make/platform/clang_linux.mk6
-rw-r--r--test/asan/CMakeLists.txt4
-rw-r--r--test/asan/TestCases/Darwin/atos-symbolizer.cc28
-rw-r--r--test/asan/TestCases/Darwin/dladdr-demangling.cc33
-rw-r--r--test/asan/TestCases/Darwin/interface_symbols_darwin.c12
-rw-r--r--test/asan/TestCases/Darwin/sandbox-symbolizer.cc29
-rw-r--r--test/asan/TestCases/Darwin/suppressions-sandbox.cc26
-rw-r--r--test/asan/TestCases/Linux/coverage-module-unloaded.cc8
-rw-r--r--test/asan/TestCases/Linux/coverage-sandboxing.cc2
-rw-r--r--test/asan/TestCases/Linux/coverage.cc16
-rw-r--r--test/asan/TestCases/Linux/interface_symbols_linux.c12
-rw-r--r--test/asan/TestCases/Linux/leak_check_segv.cc23
-rw-r--r--test/asan/TestCases/Linux/nohugepage_test.cc20
-rw-r--r--test/asan/TestCases/Linux/ptrace.cc6
-rw-r--r--test/asan/TestCases/Linux/signal_during_stop_the_world.cc60
-rw-r--r--test/asan/TestCases/Linux/sized_delete_test.cc5
-rw-r--r--test/asan/TestCases/Posix/coverage-direct.cc (renamed from test/asan/TestCases/Linux/coverage-direct.cc)0
-rw-r--r--test/asan/TestCases/Posix/coverage-fork.cc (renamed from test/asan/TestCases/Linux/coverage-fork.cc)0
-rw-r--r--test/asan/TestCases/Posix/log_path_fork_test.cc.disabled (renamed from test/asan/TestCases/log_path_fork_test.cc.disabled)0
-rw-r--r--test/asan/TestCases/Posix/start-deactivated.cc1
-rw-r--r--test/asan/TestCases/Windows/bind_io_completion_callback.cc70
-rw-r--r--test/asan/TestCases/Windows/dll_noreturn.cc2
-rw-r--r--test/asan/TestCases/Windows/dll_report_globals_symbolization_at_startup.cc40
-rw-r--r--test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc2
-rw-r--r--test/asan/TestCases/Windows/queue_user_work_item.cc55
-rw-r--r--test/asan/TestCases/Windows/queue_user_work_item_report.cc29
-rw-r--r--test/asan/TestCases/Windows/report_globals_reload_dll.cc51
-rw-r--r--test/asan/TestCases/Windows/report_globals_vs_freelibrary.cc (renamed from test/asan/TestCases/Windows/globals_multiple_dlls.cc)4
-rw-r--r--test/asan/TestCases/Windows/stack_array_left_oob.cc2
-rw-r--r--test/asan/TestCases/Windows/thread_stack_array_left_oob.cc2
-rw-r--r--test/asan/TestCases/closed-fds.cc30
-rw-r--r--test/asan/TestCases/coverage-and-lsan.cc (renamed from test/asan/TestCases/Linux/coverage-and-lsan.cc)0
-rw-r--r--test/asan/TestCases/coverage-caller-callee-total-count.cc (renamed from test/asan/TestCases/Linux/coverage-caller-callee-total-count.cc)0
-rw-r--r--test/asan/TestCases/coverage-caller-callee.cc (renamed from test/asan/TestCases/Linux/coverage-caller-callee.cc)0
-rw-r--r--test/asan/TestCases/coverage-disabled.cc (renamed from test/asan/TestCases/Linux/coverage-disabled.cc)0
-rw-r--r--test/asan/TestCases/coverage-levels.cc (renamed from test/asan/TestCases/Linux/coverage-levels.cc)11
-rw-r--r--test/asan/TestCases/coverage-maybe-open-file.cc (renamed from test/asan/TestCases/Linux/coverage-maybe-open-file.cc)1
-rw-r--r--test/asan/TestCases/coverage-order-pcs.cc56
-rw-r--r--test/asan/TestCases/coverage-reset.cc (renamed from test/asan/TestCases/Linux/coverage-reset.cc)0
-rw-r--r--test/asan/TestCases/coverage-tracing.cc (renamed from test/asan/TestCases/Linux/coverage-tracing.cc)0
-rw-r--r--test/asan/TestCases/debug_stacks.cc3
-rw-r--r--test/asan/TestCases/heap-overflow-large.cc4
-rw-r--r--test/asan/TestCases/print_summary.cc16
-rw-r--r--test/asan/TestCases/strip_path_prefix.c4
-rw-r--r--test/asan/TestCases/suppressions-exec-relative-location.cc47
-rw-r--r--test/builtins/Unit/divtc3_test.c3
-rw-r--r--test/builtins/Unit/fixtfsi_test.c65
-rw-r--r--test/builtins/Unit/fixunstfdi_test.c3
-rw-r--r--test/builtins/Unit/fixunstfsi_test.c64
-rw-r--r--test/builtins/Unit/multc3_test.c3
-rw-r--r--test/builtins/Unit/powitf2_test.c3
-rw-r--r--test/cfi/CMakeLists.txt5
-rw-r--r--test/cfi/bad-cast.cpp136
-rw-r--r--test/cfi/sibling.cpp67
-rw-r--r--test/dfsan/basic.c4
-rw-r--r--test/dfsan/custom.cc8
-rw-r--r--test/dfsan/dump_labels.c2
-rw-r--r--test/dfsan/flags.c6
-rw-r--r--test/dfsan/fncall.c4
-rw-r--r--test/dfsan/label_count.c12
-rw-r--r--test/dfsan/lit.cfg2
-rw-r--r--test/dfsan/propagate.c4
-rw-r--r--test/dfsan/vararg.c4
-rw-r--r--test/dfsan/write_callback.c4
-rw-r--r--test/msan/Linux/getresid.cc6
-rw-r--r--test/msan/Linux/glob.cc6
-rw-r--r--test/msan/Linux/glob_altdirfunc.cc6
-rw-r--r--test/msan/Linux/glob_nomatch.cc4
-rw-r--r--test/msan/Linux/sunrpc.cc12
-rw-r--r--test/msan/Linux/sunrpc_bytes.cc4
-rw-r--r--test/msan/Linux/sunrpc_string.cc4
-rw-r--r--test/msan/Linux/syscalls.cc4
-rw-r--r--test/msan/Linux/tcgetattr.cc2
-rw-r--r--test/msan/Linux/xattr.cc6
-rw-r--r--test/msan/backtrace.cc2
-rw-r--r--test/msan/c-strdup.c8
-rw-r--r--test/msan/chained_origin.cc8
-rw-r--r--test/msan/chained_origin_empty_stack.cc2
-rw-r--r--test/msan/chained_origin_limits.cc8
-rw-r--r--test/msan/chained_origin_memcpy.cc8
-rw-r--r--test/msan/chained_origin_with_signals.cc4
-rw-r--r--test/msan/check_mem_is_initialized.cc16
-rw-r--r--test/msan/cxa_atexit.cc2
-rw-r--r--test/msan/death-callback.cc8
-rw-r--r--test/msan/dlerror.cc2
-rw-r--r--test/msan/dso-origin.cc4
-rw-r--r--test/msan/dtls_test.c4
-rw-r--r--test/msan/errno.cc2
-rw-r--r--test/msan/fork.cc2
-rw-r--r--test/msan/ftime.cc2
-rw-r--r--test/msan/getaddrinfo-positive.cc4
-rw-r--r--test/msan/getaddrinfo.cc2
-rw-r--r--test/msan/getc_unlocked.c16
-rw-r--r--test/msan/heap-origin.cc16
-rw-r--r--test/msan/iconv.cc4
-rw-r--r--test/msan/if_indextoname.cc6
-rw-r--r--test/msan/ifaddrs.cc6
-rw-r--r--test/msan/initgroups.cc2
-rw-r--r--test/msan/insertvalue_origin.cc4
-rw-r--r--test/msan/ioctl.cc4
-rw-r--r--test/msan/ioctl_custom.cc8
-rw-r--r--test/msan/ioctl_sound.cc4
-rw-r--r--test/msan/keep-going-dso.cc12
-rw-r--r--test/msan/keep-going.cc16
-rw-r--r--test/msan/mallinfo.cc2
-rw-r--r--test/msan/mktime.cc4
-rw-r--r--test/msan/mmap_below_shadow.cc8
-rw-r--r--test/msan/msan_check_mem_is_initialized.cc4
-rw-r--r--test/msan/msan_dump_shadow.cc6
-rw-r--r--test/msan/msan_print_shadow.cc6
-rw-r--r--test/msan/msan_print_shadow2.cc6
-rw-r--r--test/msan/msan_print_shadow3.cc2
-rw-r--r--test/msan/mul_by_const.cc2
-rw-r--r--test/msan/no_sanitize_memory.cc16
-rw-r--r--test/msan/no_sanitize_memory_prop.cc8
-rw-r--r--test/msan/obstack.cc4
-rw-r--r--test/msan/origin-store-long.cc4
-rw-r--r--test/msan/param_tls_limit.cc6
-rw-r--r--test/msan/print_stats.cc6
-rw-r--r--test/msan/pthread_getattr_np_deadlock.cc2
-rw-r--r--test/msan/rand_r.cc4
-rw-r--r--test/msan/readdir64.cc16
-rw-r--r--test/msan/realloc-large-origin.cc4
-rw-r--r--test/msan/realloc-origin.cc4
-rw-r--r--test/msan/report-demangling.cc2
-rw-r--r--test/msan/scandir.cc6
-rw-r--r--test/msan/scandir_null.cc6
-rw-r--r--test/msan/select.cc8
-rw-r--r--test/msan/setlocale.cc2
-rw-r--r--test/msan/stack-origin.cc16
-rw-r--r--test/msan/stack-origin2.cc16
-rw-r--r--test/msan/strlen_of_shadow.cc2
-rw-r--r--test/msan/strxfrm.cc2
-rw-r--r--test/msan/sync_lock_set_and_test.cc2
-rw-r--r--test/msan/textdomain.cc2
-rw-r--r--test/msan/times.cc2
-rw-r--r--test/msan/tls_reuse.cc2
-rw-r--r--test/msan/tzset.cc2
-rw-r--r--test/msan/unaligned_read_origin.cc4
-rw-r--r--test/msan/unpoison_string.cc4
-rw-r--r--test/msan/use-after-free.cc16
-rw-r--r--test/msan/vector_cvt.cc4
-rw-r--r--test/msan/vector_select.cc4
-rw-r--r--test/sanitizer_common/CMakeLists.txt24
-rw-r--r--test/sanitizer_common/TestCases/Linux/open_memstream.cc1
-rw-r--r--test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc (renamed from test/tsan/signal_segv_handler.cc)10
-rw-r--r--test/sanitizer_common/lit.site.cfg.in2
-rw-r--r--test/tsan/java_heap_init.cc28
-rw-r--r--test/tsan/mmap_large.cc7
-rw-r--r--test/tsan/mmap_stress.cc47
-rw-r--r--test/tsan/test.h10
-rw-r--r--test/ubsan/TestCases/Integer/shift.cpp34
-rw-r--r--test/ubsan/TestCases/Integer/summary.cpp2
-rw-r--r--test/ubsan/TestCases/Misc/Linux/coverage-levels.cc (renamed from test/ubsan/TestCases/Misc/coverage-levels.cc)2
-rw-r--r--test/ubsan/TestCases/Misc/Linux/lit.local.cfg9
-rw-r--r--test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp3
283 files changed, 4258 insertions, 2424 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f3485853f..d65b396f0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -160,8 +160,6 @@ include(CompilerRTUtils)
set(COMPILER_RT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(COMPILER_RT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
-# Setup custom SDK sysroots.
-set(COMPILER_RT_LINUX_SDK_SYSROOT ${COMPILER_RT_SOURCE_DIR}/SDKs/linux)
# We support running instrumented tests when we're not cross compiling
# and target a UNIX-like system or Windows.
@@ -302,15 +300,22 @@ if(APPLE)
set(SANITIZER_MIN_OSX_VERSION 10.7)
set(CMAKE_OSX_DEPLOYMENT_TARGET "") # We're setting the flag manually below.
set(DARWIN_osx_CFLAGS -mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION}
- -isysroot ${OSX_SDK_DIR} -stdlib=libc++)
+ -stdlib=libc++)
set(DARWIN_iossim_CFLAGS
+ -stdlib=libc++
-mios-simulator-version-min=7.0 -isysroot ${IOSSIM_SDK_DIR})
set(DARWIN_osx_LINKFLAGS -mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION}
- -isysroot ${OSX_SDK_DIR} -stdlib=libc++)
+ -stdlib=libc++ -lc++)
set(DARWIN_iossim_LINKFLAGS
+ -stdlib=libc++ -lc++
-Wl,-ios_simulator_version_min,7.0.0
-mios-simulator-version-min=7.0
-isysroot ${IOSSIM_SDK_DIR})
+
+ if(OSX_SDK_DIR)
+ list(APPEND DARWIN_osx_CFLAGS -isysroot ${OSX_SDK_DIR})
+ list(APPEND DARWIN_osx_LINKFLAGS -isysroot ${OSX_SDK_DIR})
+ endif()
endif()
add_subdirectory(include)
diff --git a/LICENSE.TXT b/LICENSE.TXT
index aee8347b0..aa4115e2a 100644
--- a/LICENSE.TXT
+++ b/LICENSE.TXT
@@ -14,7 +14,7 @@ Full text of the relevant licenses is included below.
University of Illinois/NCSA
Open Source License
-Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
All rights reserved.
@@ -55,7 +55,7 @@ SOFTWARE.
==============================================================================
-Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/SDKs/README.txt b/SDKs/README.txt
deleted file mode 100644
index b95575e8c..000000000
--- a/SDKs/README.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-It is often convenient to be able to build compiler-rt libraries for a certain
-platform without having a full SDK or development environment installed.
-
-This makes it easy for users to build a compiler which can target a number of
-different platforms, without having to actively maintain full development
-environments for those platforms.
-
-Since compiler-rt's libraries typically have minimal interaction with the
-system, we achieve this by stubbing out the SDKs of certain platforms.
diff --git a/SDKs/linux/README.txt b/SDKs/linux/README.txt
deleted file mode 100644
index aa0604af7..000000000
--- a/SDKs/linux/README.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This is a stub SDK for Linux. Currently, this has only been tested on i386 and
-x86_64 using the Clang compiler.
diff --git a/SDKs/linux/usr/include/endian.h b/SDKs/linux/usr/include/endian.h
deleted file mode 100644
index 95528db15..000000000
--- a/SDKs/linux/usr/include/endian.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* ===-- endian.h - stub SDK header for compiler-rt -------------------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
- *
- * ===-----------------------------------------------------------------------===
- *
- * This is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __ENDIAN_H__
-#define __ENDIAN_H__
-
-#define __LITTLE_ENDIAN 1234
-#define __BIG_ENDIAN 4321
-
-#if defined(__LITTLE_ENDIAN__) || defined(__ORDER_LITTLE_ENDIAN__)
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#else
-#define __BYTE_ORDER __BIG_ENDIAN
-#endif
-
-#endif /* __ENDIAN_H__ */
diff --git a/SDKs/linux/usr/include/fcntl.h b/SDKs/linux/usr/include/fcntl.h
deleted file mode 100644
index a5f91e3a5..000000000
--- a/SDKs/linux/usr/include/fcntl.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* ===-- fcntl.h - stub SDK header for compiler-rt --------------------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
- *
- * ===-----------------------------------------------------------------------===
- *
- * This is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#include <sys/fcntl.h>
diff --git a/SDKs/linux/usr/include/limits.h b/SDKs/linux/usr/include/limits.h
deleted file mode 100644
index 5495a784f..000000000
--- a/SDKs/linux/usr/include/limits.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* ===-- limits.h - stub SDK header for compiler-rt -------------------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
- *
- * ===-----------------------------------------------------------------------===
- *
- * This is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __LIMITS_H__
-#define __LIMITS_H__
-
-/* This is only here as a landing pad for the include_next from the compiler's
- built-in limits.h. */
-
-#endif /* __LIMITS_H__ */
diff --git a/SDKs/linux/usr/include/stdio.h b/SDKs/linux/usr/include/stdio.h
deleted file mode 100644
index e2161daa4..000000000
--- a/SDKs/linux/usr/include/stdio.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* ===-- stdio.h - stub SDK header for compiler-rt --------------------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
- *
- * ===-----------------------------------------------------------------------===
- *
- * This is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __STDIO_H__
-#define __STDIO_H__
-
-typedef __SIZE_TYPE__ size_t;
-
-struct _IO_FILE;
-typedef struct _IO_FILE FILE;
-
-extern struct _IO_FILE *stdin;
-extern struct _IO_FILE *stdout;
-extern struct _IO_FILE *stderr;
-
-#define SEEK_SET 0 /* set file offset to offset */
-#define SEEK_CUR 1 /* set file offset to current plus offset */
-#define SEEK_END 2 /* set file offset to EOF plus offset */
-
-extern int fclose(FILE *);
-extern int fflush(FILE *);
-extern FILE *fopen(const char * restrict, const char * restrict);
-extern FILE *fdopen(int, const char * restrict);
-extern int fprintf(FILE * restrict, const char * restrict, ...);
-extern int fputc(int, FILE *);
-extern size_t fwrite(const void * restrict, size_t, size_t, FILE * restrict);
-extern size_t fread(void * restrict, size_t, size_t, FILE * restrict);
-extern long ftell(FILE *);
-extern int fseek(FILE *, long, int);
-
-#endif /* __STDIO_H__ */
diff --git a/SDKs/linux/usr/include/stdlib.h b/SDKs/linux/usr/include/stdlib.h
deleted file mode 100644
index 966b29db6..000000000
--- a/SDKs/linux/usr/include/stdlib.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* ===-- stdlib.h - stub SDK header for compiler-rt -------------------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
- *
- * ===-----------------------------------------------------------------------===
- *
- * This is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __STDLIB_H__
-#define __STDLIB_H__
-
-#define NULL ((void *)0)
-
-typedef __SIZE_TYPE__ size_t;
-
-void abort(void) __attribute__((__nothrow__)) __attribute__((__noreturn__));
-int atexit(void (*)(void)) __attribute__((__nothrow__));
-int atoi(const char *) __attribute__((__nothrow__));
-void free(void *) __attribute__((__nothrow__));
-char *getenv(const char *) __attribute__((__nothrow__))
- __attribute__((__nonnull__(1)));
- __attribute__((__warn_unused_result__));
-void *malloc(size_t) __attribute__((__nothrow__)) __attribute((__malloc__))
- __attribute__((__warn_unused_result__));
-void *realloc(void *, size_t) __attribute__((__nothrow__)) __attribute((__malloc__))
- __attribute__((__warn_unused_result__));
-
-#endif /* __STDLIB_H__ */
diff --git a/SDKs/linux/usr/include/string.h b/SDKs/linux/usr/include/string.h
deleted file mode 100644
index c7da1f57b..000000000
--- a/SDKs/linux/usr/include/string.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* ===-- string.h - stub SDK header for compiler-rt -------------------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
- *
- * ===-----------------------------------------------------------------------===
- *
- * This is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __STRING_H__
-#define __STRING_H__
-
-typedef __SIZE_TYPE__ size_t;
-
-int memcmp(const void *, const void *, size_t);
-void *memcpy(void *, const void *, size_t);
-void *memset(void *, int, size_t);
-char *strcat(char *, const char *);
-char *strcpy(char *, const char *);
-char *strdup(const char *);
-size_t strlen(const char *);
-char *strncpy(char *, const char *, size_t);
-
-#endif /* __STRING_H__ */
diff --git a/SDKs/linux/usr/include/sys/fcntl.h b/SDKs/linux/usr/include/sys/fcntl.h
deleted file mode 100644
index 1512bf9b4..000000000
--- a/SDKs/linux/usr/include/sys/fcntl.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* ===-- fcntl.h - stub SDK header for compiler-rt --------------------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
- *
- * ===-----------------------------------------------------------------------===
- *
- * This is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef _SYS_FCNTL_H_
-#define _SYS_FCNTL_H_
-
-#define O_RDONLY 0x0000
-#define O_WRONLY 0x0001
-#define O_RDWR 0x0002
-#define O_ACCMODE 0x0003
-
-#define O_CREAT 0x0200
-
-int open(const char *, int, ...);
-
-#endif /* _SYS_FCNTL_H_ */
diff --git a/SDKs/linux/usr/include/sys/mman.h b/SDKs/linux/usr/include/sys/mman.h
deleted file mode 100644
index bfb7f8bb0..000000000
--- a/SDKs/linux/usr/include/sys/mman.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* ===-- limits.h - stub SDK header for compiler-rt -------------------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
- *
- * ===-----------------------------------------------------------------------===
- *
- * This is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __SYS_MMAN_H__
-#define __SYS_MMAN_H__
-
-typedef __SIZE_TYPE__ size_t;
-
-#define PROT_NONE 0x00
-#define PROT_READ 0x01
-#define PROT_WRITE 0x02
-#define PROT_EXEC 0x04
-
-#define MAP_SHARED 0x0001
-#define MAP_PRIVATE 0x0002
-
-#define MAP_FILE 0x0000
-#define MAP_ANON 0x1000
-
-#define MS_ASYNC 0x0001
-#define MS_INVALIDATE 0x0002
-#define MS_SYNC 0x0010
-
-extern void *mmap(void *addr, size_t len, int prot, int flags, int fd,
- long long offset)
- __attribute__((__nothrow__));
-extern int munmap(void *addr, size_t len)
- __attribute__((__nothrow__));
-extern int msync(void *addr, size_t len, int flags)
- __attribute__((__nothrow__));
-extern int mprotect (void *__addr, size_t __len, int __prot)
- __attribute__((__nothrow__));
-
-#endif /* __SYS_MMAN_H__ */
diff --git a/SDKs/linux/usr/include/sys/stat.h b/SDKs/linux/usr/include/sys/stat.h
deleted file mode 100644
index 0449fddb0..000000000
--- a/SDKs/linux/usr/include/sys/stat.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* ===-- stat.h - stub SDK header for compiler-rt ---------------------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
- *
- * ===-----------------------------------------------------------------------===
- *
- * This is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __SYS_STAT_H__
-#define __SYS_STAT_H__
-
-typedef unsigned int mode_t;
-
-int mkdir(const char *, mode_t);
-
-#endif /* __SYS_STAT_H__ */
diff --git a/SDKs/linux/usr/include/sys/types.h b/SDKs/linux/usr/include/sys/types.h
deleted file mode 100644
index 10e74bbd0..000000000
--- a/SDKs/linux/usr/include/sys/types.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* ===-- stat.h - stub SDK header for compiler-rt ---------------------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
- *
- * ===-----------------------------------------------------------------------===
- *
- * This is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __SYS_TYPES_H__
-#define __SYS_TYPES_H__
-
-#endif /* __SYS_TYPES_H__ */
diff --git a/SDKs/linux/usr/include/unistd.h b/SDKs/linux/usr/include/unistd.h
deleted file mode 100644
index 773b081d4..000000000
--- a/SDKs/linux/usr/include/unistd.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* ===-- unistd.h - stub SDK header for compiler-rt -------------------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
- *
- * ===-----------------------------------------------------------------------===
- *
- * This is a stub SDK header file. This file is not part of the interface of
- * this library nor an official version of the appropriate SDK header. It is
- * intended only to stub the features of this header required by compiler-rt.
- *
- * ===-----------------------------------------------------------------------===
- */
-
-#ifndef __UNISTD_H__
-#define __UNISTD_H__
-
-enum {
- _SC_PAGESIZE = 30
-};
-
-extern long int sysconf (int __name) __attribute__ ((__nothrow__));
-
-#endif /* __UNISTD_H__ */
diff --git a/cmake/Modules/CompilerRTCompile.cmake b/cmake/Modules/CompilerRTCompile.cmake
index de73ccfc5..c883e43aa 100644
--- a/cmake/Modules/CompilerRTCompile.cmake
+++ b/cmake/Modules/CompilerRTCompile.cmake
@@ -1,5 +1,31 @@
include(LLVMParseArguments)
+# On Windows, CMAKE_*_FLAGS are built for MSVC but we use the GCC clang.exe,
+# which uses completely different flags. Translate some common flag types, and
+# drop the rest.
+function(translate_msvc_cflags out_flags msvc_flags)
+ # Insert an empty string in the list to simplify processing.
+ set(msvc_flags ";${msvc_flags}")
+
+ # Canonicalize /flag to -flag.
+ string(REPLACE ";/" ";-" msvc_flags "${msvc_flags}")
+
+ # Make space separated -D and -U flags into joined flags.
+ string(REGEX REPLACE ";-\([DU]\);" ";-\\1" msvc_flags "${msvc_flags}")
+
+ set(clang_flags "")
+ foreach(flag ${msvc_flags})
+ if ("${flag}" MATCHES "^-[DU]")
+ # Pass through basic command line macro definitions (-DNDEBUG).
+ list(APPEND clang_flags "${flag}")
+ elseif ("${flag}" MATCHES "^-O[2x]")
+ # Canonicalize normal optimization flags to -O2.
+ list(APPEND clang_flags "-O2")
+ endif()
+ endforeach()
+ set(${out_flags} "${clang_flags}" PARENT_SCOPE)
+endfunction()
+
# Compile a source into an object file with COMPILER_RT_TEST_COMPILER using
# a provided compile flags and dependenices.
# clang_compile(<object> <source>
@@ -20,13 +46,11 @@ macro(clang_compile object_file source)
else()
string(REPLACE " " ";" global_flags "${CMAKE_C_FLAGS}")
endif()
- # On Windows, CMAKE_*_FLAGS are built for MSVC but we use the GCC clang.exe
- # which doesn't support flags starting with "/smth". Replace those with
- # "-smth" equivalents.
- if(MSVC)
- string(REGEX REPLACE "^/" "-" global_flags "${global_flags}")
- string(REPLACE ";/" ";-" global_flags "${global_flags}")
+
+ if (MSVC)
+ translate_msvc_cflags(global_flags "${global_flags}")
endif()
+
# Ignore unknown warnings. CMAKE_CXX_FLAGS may contain GCC-specific options
# which are not supported by Clang.
list(APPEND global_flags -Wno-unknown-warning-option)
diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake
index 9c4c8deea..f52639bdb 100644
--- a/cmake/config-ix.cmake
+++ b/cmake/config-ix.cmake
@@ -161,10 +161,11 @@ else()
if("${LLVM_NATIVE_ARCH}" STREQUAL "X86")
if(NOT MSVC)
test_target_arch(x86_64 "" "-m64")
+ # FIXME: We build runtimes for both i686 and i386, as "clang -m32" may
+ # target different variant than "$CMAKE_C_COMPILER -m32". This part should
+ # be gone after we resolve PR14109.
test_target_arch(i686 __i686__ "-m32")
- if(NOT CAN_TARGET_i686)
- test_target_arch(i386 __i386__ "-m32")
- endif()
+ test_target_arch(i386 __i386__ "-m32")
else()
test_target_arch(i386 "" "")
endif()
@@ -220,14 +221,14 @@ endfunction()
# Architectures supported by compiler-rt libraries.
filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH
x86_64 i386 i686 powerpc64 powerpc64le arm aarch64 mips mips64 mipsel mips64el)
-filter_available_targets(ASAN_SUPPORTED_ARCH
- x86_64 i386 i686 powerpc64 powerpc64le arm mips mipsel mips64 mips64el)
-filter_available_targets(DFSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
-filter_available_targets(LSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
# LSan common files should be available on all architectures supported
# by other sanitizers (even if they build into dummy object files).
filter_available_targets(LSAN_COMMON_SUPPORTED_ARCH
${SANITIZER_COMMON_SUPPORTED_ARCH})
+filter_available_targets(ASAN_SUPPORTED_ARCH
+ x86_64 i386 i686 powerpc64 powerpc64le arm mips mipsel mips64 mips64el)
+filter_available_targets(DFSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
+filter_available_targets(LSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
filter_available_targets(MSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
filter_available_targets(PROFILE_SUPPORTED_ARCH x86_64 i386 i686 arm mips mips64
mipsel mips64el aarch64 powerpc64 powerpc64le)
@@ -276,13 +277,6 @@ else()
set(COMPILER_RT_HAS_LSAN FALSE)
endif()
-if (COMPILER_RT_HAS_SANITIZER_COMMON AND LSAN_COMMON_SUPPORTED_ARCH AND
- OS_NAME MATCHES "Darwin|Linux|FreeBSD|Android")
- set(COMPILER_RT_HAS_LSAN_COMMON TRUE)
-else()
- set(COMPILER_RT_HAS_LSAN_COMMON FALSE)
-endif()
-
if (COMPILER_RT_HAS_SANITIZER_COMMON AND MSAN_SUPPORTED_ARCH AND
OS_NAME MATCHES "Linux")
set(COMPILER_RT_HAS_MSAN TRUE)
diff --git a/include/sanitizer/coverage_interface.h b/include/sanitizer/coverage_interface.h
index 88a7e4800..404b71e30 100644
--- a/include/sanitizer/coverage_interface.h
+++ b/include/sanitizer/coverage_interface.h
@@ -39,6 +39,23 @@ extern "C" {
// Some of the entries in *data will be zero.
uintptr_t __sanitizer_get_coverage_guards(uintptr_t **data);
+ // The coverage instrumentation may optionally provide imprecise counters.
+ // Rather than exposing the counter values to the user we instead map
+ // the counters to a bitset.
+ // Every counter is associated with 8 bits in the bitset.
+ // We define 8 value ranges: 1, 2, 3, 4-7, 8-15, 16-31, 32-127, 128+
+ // The i-th bit is set to 1 if the counter value is in the i-th range.
+ // This counter-based coverage implementation is *not* thread-safe.
+
+ // Returns the number of registered coverage counters.
+ uintptr_t __sanitizer_get_number_of_counters();
+ // Updates the counter 'bitset', clears the counters and returns the number of
+ // new bits in 'bitset'.
+ // If 'bitset' is nullptr, only clears the counters.
+ // Otherwise 'bitset' should be at least
+ // __sanitizer_get_number_of_counters bytes long and 8-aligned.
+ uintptr_t
+ __sanitizer_update_counter_bitset_and_clear_counters(uint8_t *bitset);
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 6929e682f..91a7037e3 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -7,6 +7,7 @@ include(SanitizerUtils)
if(COMPILER_RT_HAS_SANITIZER_COMMON)
add_subdirectory(interception)
add_subdirectory(sanitizer_common)
+ add_subdirectory(lsan)
endif()
if(COMPILER_RT_HAS_ASAN)
@@ -19,10 +20,6 @@ if(COMPILER_RT_HAS_DFSAN)
add_subdirectory(dfsan)
endif()
-if(COMPILER_RT_HAS_LSAN OR COMPILER_RT_HAS_LSAN_COMMON)
- add_subdirectory(lsan)
-endif()
-
if(COMPILER_RT_HAS_MSAN)
add_subdirectory(msan)
endif()
diff --git a/lib/asan/Android.mk b/lib/asan/Android.mk
index 4314c0278..ccb454570 100644
--- a/lib/asan/Android.mk
+++ b/lib/asan/Android.mk
@@ -79,6 +79,7 @@ asan_rtl_files := \
../sanitizer_common/sanitizer_symbolizer_libbacktrace.cc \
../sanitizer_common/sanitizer_symbolizer_libcdep.cc \
../sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc \
+ ../sanitizer_common/sanitizer_symbolizer_process_libcdep.cc \
../sanitizer_common/sanitizer_symbolizer_win.cc \
../sanitizer_common/sanitizer_thread_registry.cc \
../sanitizer_common/sanitizer_tls_get_addr.cc \
diff --git a/lib/asan/CMakeLists.txt b/lib/asan/CMakeLists.txt
index 90cb6f843..8b771fbe6 100644
--- a/lib/asan/CMakeLists.txt
+++ b/lib/asan/CMakeLists.txt
@@ -106,12 +106,8 @@ else()
set(ASAN_COMMON_RUNTIME_OBJECTS
$<TARGET_OBJECTS:RTInterception.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
- $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>)
- if(NOT WIN32)
- # We can't build Leak Sanitizer on Windows yet.
- list(APPEND ASAN_COMMON_RUNTIME_OBJECTS
- $<TARGET_OBJECTS:RTLSanCommon.${arch}>)
- endif()
+ $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
+ $<TARGET_OBJECTS:RTLSanCommon.${arch}>)
add_compiler_rt_runtime(clang_rt.asan-${arch} ${arch} STATIC
SOURCES $<TARGET_OBJECTS:RTAsan_preinit.${arch}>
diff --git a/lib/asan/asan_globals.cc b/lib/asan/asan_globals.cc
index 853a18102..8906d1eed 100644
--- a/lib/asan/asan_globals.cc
+++ b/lib/asan/asan_globals.cc
@@ -212,20 +212,6 @@ void StopInitOrderChecking() {
}
}
-#if SANITIZER_WINDOWS // Should only be called on Windows.
-SANITIZER_INTERFACE_ATTRIBUTE
-void UnregisterGlobalsInRange(void *beg, void *end) {
- if (!flags()->report_globals)
- return;
- BlockingMutexLock lock(&mu_for_globals);
- for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
- void *address = (void *)l->g->beg;
- if (beg <= address && address < end)
- UnregisterGlobal(l->g);
- }
-}
-#endif
-
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc
index df5769692..585181cce 100644
--- a/lib/asan/asan_interceptors.cc
+++ b/lib/asan/asan_interceptors.cc
@@ -65,7 +65,7 @@ struct AsanInterceptorContext {
} \
if (!suppressed) { \
GET_CURRENT_PC_BP_SP; \
- __asan_report_error(pc, bp, sp, __bad, isWrite, __size); \
+ __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0); \
} \
} \
} while (0)
@@ -120,17 +120,6 @@ using namespace __asan; // NOLINT
DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
-#if !SANITIZER_MAC
-#define ASAN_INTERCEPT_FUNC(name) \
- do { \
- if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \
- VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
- } while (0)
-#else
-// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
-#define ASAN_INTERCEPT_FUNC(name)
-#endif // SANITIZER_MAC
-
#define ASAN_INTERCEPTOR_ENTER(ctx, func) \
AsanInterceptorContext _ctx = {#func}; \
ctx = (void *)&_ctx; \
@@ -206,12 +195,6 @@ struct ThreadStartParam {
};
static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
-#if SANITIZER_WINDOWS
- // FIXME: this is a bandaid fix for PR22025.
- AsanThread *t = (AsanThread*)arg;
- SetCurrentThread(t);
- return t->ThreadStart(GetTid(), /* signal_thread_is_registered */ nullptr);
-#else
ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
AsanThread *t = nullptr;
while ((t = reinterpret_cast<AsanThread *>(
@@ -219,7 +202,6 @@ static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
internal_sched_yield();
SetCurrentThread(t);
return t->ThreadStart(GetTid(), &param->is_registered);
-#endif
}
#if ASAN_INTERCEPT_PTHREAD_CREATE
@@ -363,30 +345,6 @@ INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
}
#endif
-#if SANITIZER_WINDOWS
-INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
- CHECK(REAL(RaiseException));
- __asan_handle_no_return();
- REAL(RaiseException)(a, b, c, d);
-}
-
-INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) {
- CHECK(REAL(_except_handler3));
- __asan_handle_no_return();
- return REAL(_except_handler3)(a, b, c, d);
-}
-
-#if ASAN_DYNAMIC
-// This handler is named differently in -MT and -MD CRTs.
-#define _except_handler4 _except_handler4_common
-#endif
-INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
- CHECK(REAL(_except_handler4));
- __asan_handle_no_return();
- return REAL(_except_handler4)(a, b, c, d);
-}
-#endif
-
static inline int CharCmp(unsigned char c1, unsigned char c2) {
return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
}
@@ -813,36 +771,6 @@ INTERCEPTOR(int, fork, void) {
}
#endif // ASAN_INTERCEPT_FORK
-#if SANITIZER_WINDOWS
-INTERCEPTOR_WINAPI(DWORD, CreateThread,
- void* security, uptr stack_size,
- DWORD (__stdcall *start_routine)(void*), void* arg,
- DWORD thr_flags, void* tid) {
- // Strict init-order checking is thread-hostile.
- if (flags()->strict_init_order)
- StopInitOrderChecking();
- GET_STACK_TRACE_THREAD;
- // FIXME: The CreateThread interceptor is not the same as a pthread_create
- // one. This is a bandaid fix for PR22025.
- bool detached = false; // FIXME: how can we determine it on Windows?
- u32 current_tid = GetCurrentTidOrInvalid();
- AsanThread *t =
- AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
- return REAL(CreateThread)(security, stack_size,
- asan_thread_start, t, thr_flags, tid);
-}
-
-namespace __asan {
-void InitializeWindowsInterceptors() {
- ASAN_INTERCEPT_FUNC(CreateThread);
- ASAN_INTERCEPT_FUNC(RaiseException);
- ASAN_INTERCEPT_FUNC(_except_handler3);
- ASAN_INTERCEPT_FUNC(_except_handler4);
-}
-
-} // namespace __asan
-#endif
-
// ---------------------- InitializeAsanInterceptors ---------------- {{{1
namespace __asan {
void InitializeAsanInterceptors() {
@@ -925,10 +853,7 @@ void InitializeAsanInterceptors() {
ASAN_INTERCEPT_FUNC(fork);
#endif
- // Some Windows-specific interceptors.
-#if SANITIZER_WINDOWS
- InitializeWindowsInterceptors();
-#endif
+ InitializePlatformInterceptors();
VReport(1, "AddressSanitizer: libc interceptors initialized\n");
}
diff --git a/lib/asan/asan_interceptors.h b/lib/asan/asan_interceptors.h
index ee3b82aa7..488ada78a 100644
--- a/lib/asan/asan_interceptors.h
+++ b/lib/asan/asan_interceptors.h
@@ -92,9 +92,21 @@ struct sigaction;
DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act,
struct sigaction *oldact)
+#if !SANITIZER_MAC
+#define ASAN_INTERCEPT_FUNC(name) \
+ do { \
+ if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \
+ VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
+ } while (0)
+#else
+// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
+#define ASAN_INTERCEPT_FUNC(name)
+#endif // SANITIZER_MAC
+
namespace __asan {
void InitializeAsanInterceptors();
+void InitializePlatformInterceptors();
#define ENSURE_ASAN_INITED() do { \
CHECK(!asan_init_is_running); \
diff --git a/lib/asan/asan_interface_internal.h b/lib/asan/asan_interface_internal.h
index ea7540f6b..8ed4ee367 100644
--- a/lib/asan/asan_interface_internal.h
+++ b/lib/asan/asan_interface_internal.h
@@ -128,7 +128,7 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
void __asan_report_error(uptr pc, uptr bp, uptr sp,
- uptr addr, int is_write, uptr access_size);
+ uptr addr, int is_write, uptr access_size, u32 exp);
SANITIZER_INTERFACE_ATTRIBUTE
int __asan_set_error_exit_code(int exit_code);
@@ -165,6 +165,21 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN(uptr p, uptr size);
SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN(uptr p, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load1(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load2(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load4(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load8(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load16(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store1(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store2(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store4(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store8(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store16(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_loadN(uptr p, uptr size,
+ u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_storeN(uptr p, uptr size,
+ u32 exp);
+
SANITIZER_INTERFACE_ATTRIBUTE
void* __asan_memcpy(void *dst, const void *src, uptr size);
SANITIZER_INTERFACE_ATTRIBUTE
diff --git a/lib/asan/asan_internal.h b/lib/asan/asan_internal.h
index ffd3ff82d..394e46063 100644
--- a/lib/asan/asan_internal.h
+++ b/lib/asan/asan_internal.h
@@ -62,21 +62,6 @@ namespace __asan {
class AsanThread;
using __sanitizer::StackTrace;
-struct SignalContext {
- void *context;
- uptr addr;
- uptr pc;
- uptr sp;
- uptr bp;
-
- SignalContext(void *context, uptr addr, uptr pc, uptr sp, uptr bp) :
- context(context), addr(addr), pc(pc), sp(sp), bp(bp) {
- }
-
- // Creates signal context in a platform-specific manner.
- static SignalContext Create(void *siginfo, void *context);
-};
-
void AsanInitFromRtl();
// asan_rtl.cc
@@ -90,7 +75,6 @@ void *AsanDoesNotSupportStaticLinkage();
void AsanCheckDynamicRTPrereqs();
void AsanCheckIncompatibleRT();
-void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);
void AsanOnSIGSEGV(int, void *siginfo, void *context);
void DisableReexec();
diff --git a/lib/asan/asan_linux.cc b/lib/asan/asan_linux.cc
index 8e8bafd47..f4f187f72 100644
--- a/lib/asan/asan_linux.cc
+++ b/lib/asan/asan_linux.cc
@@ -68,6 +68,8 @@ asan_rt_version_t __asan_rt_version;
namespace __asan {
+void InitializePlatformInterceptors() {}
+
void DisableReexec() {
// No need to re-exec on Linux.
}
@@ -152,78 +154,6 @@ void AsanCheckIncompatibleRT() {
}
#endif // SANITIZER_ANDROID
-void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
-#if defined(__arm__)
- ucontext_t *ucontext = (ucontext_t*)context;
- *pc = ucontext->uc_mcontext.arm_pc;
- *bp = ucontext->uc_mcontext.arm_fp;
- *sp = ucontext->uc_mcontext.arm_sp;
-#elif defined(__aarch64__)
- ucontext_t *ucontext = (ucontext_t*)context;
- *pc = ucontext->uc_mcontext.pc;
- *bp = ucontext->uc_mcontext.regs[29];
- *sp = ucontext->uc_mcontext.sp;
-#elif defined(__hppa__)
- ucontext_t *ucontext = (ucontext_t*)context;
- *pc = ucontext->uc_mcontext.sc_iaoq[0];
- /* GCC uses %r3 whenever a frame pointer is needed. */
- *bp = ucontext->uc_mcontext.sc_gr[3];
- *sp = ucontext->uc_mcontext.sc_gr[30];
-#elif defined(__x86_64__)
-# if SANITIZER_FREEBSD
- ucontext_t *ucontext = (ucontext_t*)context;
- *pc = ucontext->uc_mcontext.mc_rip;
- *bp = ucontext->uc_mcontext.mc_rbp;
- *sp = ucontext->uc_mcontext.mc_rsp;
-# else
- ucontext_t *ucontext = (ucontext_t*)context;
- *pc = ucontext->uc_mcontext.gregs[REG_RIP];
- *bp = ucontext->uc_mcontext.gregs[REG_RBP];
- *sp = ucontext->uc_mcontext.gregs[REG_RSP];
-# endif
-#elif defined(__i386__)
-# if SANITIZER_FREEBSD
- ucontext_t *ucontext = (ucontext_t*)context;
- *pc = ucontext->uc_mcontext.mc_eip;
- *bp = ucontext->uc_mcontext.mc_ebp;
- *sp = ucontext->uc_mcontext.mc_esp;
-# else
- ucontext_t *ucontext = (ucontext_t*)context;
- *pc = ucontext->uc_mcontext.gregs[REG_EIP];
- *bp = ucontext->uc_mcontext.gregs[REG_EBP];
- *sp = ucontext->uc_mcontext.gregs[REG_ESP];
-# endif
-#elif defined(__powerpc__) || defined(__powerpc64__)
- ucontext_t *ucontext = (ucontext_t*)context;
- *pc = ucontext->uc_mcontext.regs->nip;
- *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
- // The powerpc{,64}-linux ABIs do not specify r31 as the frame
- // pointer, but GCC always uses r31 when we need a frame pointer.
- *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
-#elif defined(__sparc__)
- ucontext_t *ucontext = (ucontext_t*)context;
- uptr *stk_ptr;
-# if defined (__arch64__)
- *pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
- *sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
- stk_ptr = (uptr *) (*sp + 2047);
- *bp = stk_ptr[15];
-# else
- *pc = ucontext->uc_mcontext.gregs[REG_PC];
- *sp = ucontext->uc_mcontext.gregs[REG_O6];
- stk_ptr = (uptr *) *sp;
- *bp = stk_ptr[15];
-# endif
-#elif defined(__mips__)
- ucontext_t *ucontext = (ucontext_t*)context;
- *pc = ucontext->uc_mcontext.gregs[31];
- *bp = ucontext->uc_mcontext.gregs[30];
- *sp = ucontext->uc_mcontext.gregs[29];
-#else
-# error "Unsupported arch"
-#endif
-}
-
void AsanPlatformThreadInit() {
// Nothing here for now.
}
diff --git a/lib/asan/asan_mac.cc b/lib/asan/asan_mac.cc
index b35368617..b2618d729 100644
--- a/lib/asan/asan_mac.cc
+++ b/lib/asan/asan_mac.cc
@@ -40,19 +40,7 @@
namespace __asan {
-void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
- ucontext_t *ucontext = (ucontext_t*)context;
-# if SANITIZER_WORDSIZE == 64
- *pc = ucontext->uc_mcontext->__ss.__rip;
- *bp = ucontext->uc_mcontext->__ss.__rbp;
- *sp = ucontext->uc_mcontext->__ss.__rsp;
-# else
- *pc = ucontext->uc_mcontext->__ss.__eip;
- *bp = ucontext->uc_mcontext->__ss.__ebp;
- *sp = ucontext->uc_mcontext->__ss.__esp;
-# endif // SANITIZER_WORDSIZE
-}
-
+void InitializePlatformInterceptors() {}
bool PlatformHasDifferentMemcpyAndMemmove() {
// On OS X 10.7 memcpy() and memmove() are both resolved
diff --git a/lib/asan/asan_poisoning.cc b/lib/asan/asan_poisoning.cc
index e2b1f4dc4..569d359aa 100644
--- a/lib/asan/asan_poisoning.cc
+++ b/lib/asan/asan_poisoning.cc
@@ -112,7 +112,7 @@ void __asan_poison_memory_region(void const volatile *addr, uptr size) {
if (!flags()->allow_user_poisoning || size == 0) return;
uptr beg_addr = (uptr)addr;
uptr end_addr = beg_addr + size;
- VPrintf(1, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr,
+ VPrintf(3, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr,
(void *)end_addr);
ShadowSegmentEndpoint beg(beg_addr);
ShadowSegmentEndpoint end(end_addr);
@@ -152,7 +152,7 @@ void __asan_unpoison_memory_region(void const volatile *addr, uptr size) {
if (!flags()->allow_user_poisoning || size == 0) return;
uptr beg_addr = (uptr)addr;
uptr end_addr = beg_addr + size;
- VPrintf(1, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr,
+ VPrintf(3, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr,
(void *)end_addr);
ShadowSegmentEndpoint beg(beg_addr);
ShadowSegmentEndpoint end(end_addr);
@@ -218,7 +218,7 @@ uptr __asan_region_is_poisoned(uptr beg, uptr size) {
__asan::AddressIsPoisoned(__p + __size - 1))) { \
GET_CURRENT_PC_BP_SP; \
uptr __bad = __asan_region_is_poisoned(__p, __size); \
- __asan_report_error(pc, bp, sp, __bad, isWrite, __size);\
+ __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0);\
} \
} while (false); \
diff --git a/lib/asan/asan_posix.cc b/lib/asan/asan_posix.cc
index ad31458df..4652ddee0 100644
--- a/lib/asan/asan_posix.cc
+++ b/lib/asan/asan_posix.cc
@@ -32,13 +32,6 @@
namespace __asan {
-SignalContext SignalContext::Create(void *siginfo, void *context) {
- uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr;
- uptr pc, sp, bp;
- GetPcSpBp(context, &pc, &sp, &bp);
- return SignalContext(context, addr, pc, sp, bp);
-}
-
void AsanOnSIGSEGV(int, void *siginfo, void *context) {
ScopedDeadlySignal signal_scope(GetCurrentThread());
int code = (int)((siginfo_t*)siginfo)->si_code;
diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc
index ad75262b7..c1c340c45 100644
--- a/lib/asan/asan_report.cc
+++ b/lib/asan/asan_report.cc
@@ -939,9 +939,18 @@ void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
using namespace __asan; // NOLINT
void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
- uptr access_size) {
+ uptr access_size, u32 exp) {
ENABLE_FRAME_POINTER;
+ // Optimization experiments.
+ // The experiments can be used to evaluate potential optimizations that remove
+ // instrumentation (assess false negatives). Instead of completely removing
+ // some instrumentation, compiler can emit special calls into runtime
+ // (e.g. __asan_report_exp_load1 instead of __asan_report_load1) and pass
+ // mask of experiments (exp).
+ // The reaction to a non-zero value of exp is to be defined.
+ (void)exp;
+
// Determine the error type.
const char *bug_descr = "unknown-crash";
if (AddrIsInMem(addr)) {
diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc
index 9126e71a6..f3466151f 100644
--- a/lib/asan/asan_rtl.cc
+++ b/lib/asan/asan_rtl.cc
@@ -112,11 +112,15 @@ static void OnLowLevelAllocate(uptr ptr, uptr size) {
// -------------------------- Run-time entry ------------------- {{{1
// exported functions
#define ASAN_REPORT_ERROR(type, is_write, size) \
-extern "C" NOINLINE INTERFACE_ATTRIBUTE \
-void __asan_report_ ## type ## size(uptr addr); \
-void __asan_report_ ## type ## size(uptr addr) { \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+void __asan_report_ ## type ## size(uptr addr) { \
+ GET_CALLER_PC_BP_SP; \
+ __asan_report_error(pc, bp, sp, addr, is_write, size, 0); \
+} \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+void __asan_report_exp_ ## type ## size(uptr addr, u32 exp) { \
GET_CALLER_PC_BP_SP; \
- __asan_report_error(pc, bp, sp, addr, is_write, size); \
+ __asan_report_error(pc, bp, sp, addr, is_write, size, exp); \
}
ASAN_REPORT_ERROR(load, false, 1)
@@ -132,18 +136,20 @@ ASAN_REPORT_ERROR(store, true, 16)
#define ASAN_REPORT_ERROR_N(type, is_write) \
extern "C" NOINLINE INTERFACE_ATTRIBUTE \
-void __asan_report_ ## type ## _n(uptr addr, uptr size); \
void __asan_report_ ## type ## _n(uptr addr, uptr size) { \
GET_CALLER_PC_BP_SP; \
- __asan_report_error(pc, bp, sp, addr, is_write, size); \
+ __asan_report_error(pc, bp, sp, addr, is_write, size, 0); \
+} \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+void __asan_report_exp_ ## type ## _n(uptr addr, uptr size, u32 exp) { \
+ GET_CALLER_PC_BP_SP; \
+ __asan_report_error(pc, bp, sp, addr, is_write, size, exp); \
}
ASAN_REPORT_ERROR_N(load, false)
ASAN_REPORT_ERROR_N(store, true)
-#define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \
- extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_##type##size(uptr addr); \
- void __asan_##type##size(uptr addr) { \
+#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg) \
uptr sp = MEM_TO_SHADOW(addr); \
uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \
: *reinterpret_cast<u16 *>(sp); \
@@ -155,10 +161,19 @@ ASAN_REPORT_ERROR_N(store, true)
*__asan_test_only_reported_buggy_pointer = addr; \
} else { \
GET_CALLER_PC_BP_SP; \
- __asan_report_error(pc, bp, sp, addr, is_write, size); \
+ __asan_report_error(pc, bp, sp, addr, is_write, size, exp_arg); \
} \
} \
- } \
+ }
+
+#define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \
+ extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+ void __asan_##type##size(uptr addr) { \
+ ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0) \
+ } \
+ extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+ void __asan_exp_##type##size(uptr addr, u32 exp) { \
+ ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp) \
}
ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1)
@@ -173,18 +188,38 @@ ASAN_MEMORY_ACCESS_CALLBACK(store, true, 8)
ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16)
extern "C"
-NOINLINE INTERFACE_ATTRIBUTE void __asan_loadN(uptr addr, uptr size) {
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_loadN(uptr addr, uptr size) {
+ if (__asan_region_is_poisoned(addr, size)) {
+ GET_CALLER_PC_BP_SP;
+ __asan_report_error(pc, bp, sp, addr, false, size, 0);
+ }
+}
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_exp_loadN(uptr addr, uptr size, u32 exp) {
+ if (__asan_region_is_poisoned(addr, size)) {
+ GET_CALLER_PC_BP_SP;
+ __asan_report_error(pc, bp, sp, addr, false, size, exp);
+ }
+}
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_storeN(uptr addr, uptr size) {
if (__asan_region_is_poisoned(addr, size)) {
GET_CALLER_PC_BP_SP;
- __asan_report_error(pc, bp, sp, addr, false, size);
+ __asan_report_error(pc, bp, sp, addr, true, size, 0);
}
}
extern "C"
-NOINLINE INTERFACE_ATTRIBUTE void __asan_storeN(uptr addr, uptr size) {
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_exp_storeN(uptr addr, uptr size, u32 exp) {
if (__asan_region_is_poisoned(addr, size)) {
GET_CALLER_PC_BP_SP;
- __asan_report_error(pc, bp, sp, addr, true, size);
+ __asan_report_error(pc, bp, sp, addr, true, size, exp);
}
}
@@ -203,26 +238,40 @@ static NOINLINE void force_interface_symbols() {
case 3: __asan_report_load4(0); break;
case 4: __asan_report_load8(0); break;
case 5: __asan_report_load16(0); break;
- case 6: __asan_report_store1(0); break;
- case 7: __asan_report_store2(0); break;
- case 8: __asan_report_store4(0); break;
- case 9: __asan_report_store8(0); break;
- case 10: __asan_report_store16(0); break;
- case 12: __asan_register_globals(0, 0); break;
- case 13: __asan_unregister_globals(0, 0); break;
- case 14: __asan_set_death_callback(0); break;
- case 15: __asan_set_error_report_callback(0); break;
- case 16: __asan_handle_no_return(); break;
- case 17: __asan_address_is_poisoned(0); break;
- case 25: __asan_poison_memory_region(0, 0); break;
- case 26: __asan_unpoison_memory_region(0, 0); break;
- case 27: __asan_set_error_exit_code(0); break;
- case 30: __asan_before_dynamic_init(0); break;
- case 31: __asan_after_dynamic_init(); break;
- case 32: __asan_poison_stack_memory(0, 0); break;
- case 33: __asan_unpoison_stack_memory(0, 0); break;
- case 34: __asan_region_is_poisoned(0, 0); break;
- case 35: __asan_describe_address(0); break;
+ case 6: __asan_report_load_n(0, 0); break;
+ case 7: __asan_report_store1(0); break;
+ case 8: __asan_report_store2(0); break;
+ case 9: __asan_report_store4(0); break;
+ case 10: __asan_report_store8(0); break;
+ case 11: __asan_report_store16(0); break;
+ case 12: __asan_report_store_n(0, 0); break;
+ case 13: __asan_report_exp_load1(0, 0); break;
+ case 14: __asan_report_exp_load2(0, 0); break;
+ case 15: __asan_report_exp_load4(0, 0); break;
+ case 16: __asan_report_exp_load8(0, 0); break;
+ case 17: __asan_report_exp_load16(0, 0); break;
+ case 18: __asan_report_exp_load_n(0, 0, 0); break;
+ case 19: __asan_report_exp_store1(0, 0); break;
+ case 20: __asan_report_exp_store2(0, 0); break;
+ case 21: __asan_report_exp_store4(0, 0); break;
+ case 22: __asan_report_exp_store8(0, 0); break;
+ case 23: __asan_report_exp_store16(0, 0); break;
+ case 24: __asan_report_exp_store_n(0, 0, 0); break;
+ case 25: __asan_register_globals(0, 0); break;
+ case 26: __asan_unregister_globals(0, 0); break;
+ case 27: __asan_set_death_callback(0); break;
+ case 28: __asan_set_error_report_callback(0); break;
+ case 29: __asan_handle_no_return(); break;
+ case 30: __asan_address_is_poisoned(0); break;
+ case 31: __asan_poison_memory_region(0, 0); break;
+ case 32: __asan_unpoison_memory_region(0, 0); break;
+ case 33: __asan_set_error_exit_code(0); break;
+ case 34: __asan_before_dynamic_init(0); break;
+ case 35: __asan_after_dynamic_init(); break;
+ case 36: __asan_poison_stack_memory(0, 0); break;
+ case 37: __asan_unpoison_stack_memory(0, 0); break;
+ case 38: __asan_region_is_poisoned(0, 0); break;
+ case 39: __asan_describe_address(0); break;
}
}
diff --git a/lib/asan/asan_suppressions.cc b/lib/asan/asan_suppressions.cc
index 3f76e20e4..41887b5c8 100644
--- a/lib/asan/asan_suppressions.cc
+++ b/lib/asan/asan_suppressions.cc
@@ -81,14 +81,10 @@ bool IsStackTraceSuppressed(const StackTrace *stack) {
uptr addr = stack->trace[i];
if (suppression_ctx->HasSuppressionType(kInterceptorViaLibrary)) {
- const char *module_name;
- uptr module_offset;
// Match "interceptor_via_lib" suppressions.
- if (symbolizer->GetModuleNameAndOffsetForPC(addr, &module_name,
- &module_offset) &&
- suppression_ctx->Match(module_name, kInterceptorViaLibrary, &s)) {
- return true;
- }
+ if (const char *module_name = symbolizer->GetModuleNameForPc(addr))
+ if (suppression_ctx->Match(module_name, kInterceptorViaLibrary, &s))
+ return true;
}
if (suppression_ctx->HasSuppressionType(kInterceptorViaFunction)) {
diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc
index 5b1d0da3a..addb3d40a 100644
--- a/lib/asan/asan_win.cc
+++ b/lib/asan/asan_win.cc
@@ -22,10 +22,13 @@
#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_report.h"
+#include "asan_stack.h"
#include "asan_thread.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_mutex.h"
+using namespace __asan; // NOLINT
+
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
int __asan_should_detect_stack_use_after_return() {
@@ -33,6 +36,7 @@ int __asan_should_detect_stack_use_after_return() {
return __asan_option_detect_stack_use_after_return;
}
+// -------------------- A workaround for the abscence of weak symbols ----- {{{
// We don't have a direct equivalent of weak symbols when using MSVC, but we can
// use the /alternatename directive to tell the linker to default a specific
// symbol to a specific value, which works nicely for allocator hooks and
@@ -47,11 +51,105 @@ void __asan_default_on_error() {}
#pragma comment(linker, "/alternatename:___asan_default_options=___asan_default_default_options") // NOLINT
#pragma comment(linker, "/alternatename:___asan_default_suppressions=___asan_default_default_suppressions") // NOLINT
#pragma comment(linker, "/alternatename:___asan_on_error=___asan_default_on_error") // NOLINT
+// }}}
} // extern "C"
+// ---------------------- Windows-specific inteceptors ---------------- {{{
+INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
+ CHECK(REAL(RaiseException));
+ __asan_handle_no_return();
+ REAL(RaiseException)(a, b, c, d);
+}
+
+INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) {
+ CHECK(REAL(_except_handler3));
+ __asan_handle_no_return();
+ return REAL(_except_handler3)(a, b, c, d);
+}
+
+#if ASAN_DYNAMIC
+// This handler is named differently in -MT and -MD CRTs.
+#define _except_handler4 _except_handler4_common
+#endif
+INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
+ CHECK(REAL(_except_handler4));
+ __asan_handle_no_return();
+ return REAL(_except_handler4)(a, b, c, d);
+}
+
+static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
+ AsanThread *t = (AsanThread*)arg;
+ SetCurrentThread(t);
+ return t->ThreadStart(GetTid(), /* signal_thread_is_registered */ nullptr);
+}
+
+INTERCEPTOR_WINAPI(DWORD, CreateThread,
+ void* security, uptr stack_size,
+ DWORD (__stdcall *start_routine)(void*), void* arg,
+ DWORD thr_flags, void* tid) {
+ // Strict init-order checking is thread-hostile.
+ if (flags()->strict_init_order)
+ StopInitOrderChecking();
+ GET_STACK_TRACE_THREAD;
+ // FIXME: The CreateThread interceptor is not the same as a pthread_create
+ // one. This is a bandaid fix for PR22025.
+ bool detached = false; // FIXME: how can we determine it on Windows?
+ u32 current_tid = GetCurrentTidOrInvalid();
+ AsanThread *t =
+ AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
+ return REAL(CreateThread)(security, stack_size,
+ asan_thread_start, t, thr_flags, tid);
+}
+
+namespace {
+BlockingMutex mu_for_thread_tracking(LINKER_INITIALIZED);
+
+void EnsureWorkerThreadRegistered() {
+ // FIXME: GetCurrentThread relies on TSD, which might not play well with
+ // system thread pools. We might want to use something like reference
+ // counting to zero out GetCurrentThread() underlying storage when the last
+ // work item finishes? Or can we disable reclaiming of threads in the pool?
+ BlockingMutexLock l(&mu_for_thread_tracking);
+ if (__asan::GetCurrentThread())
+ return;
+
+ AsanThread *t = AsanThread::Create(
+ /* start_routine */ nullptr, /* arg */ nullptr,
+ /* parent_tid */ -1, /* stack */ nullptr, /* detached */ true);
+ t->Init();
+ asanThreadRegistry().StartThread(t->tid(), 0, 0);
+ SetCurrentThread(t);
+}
+} // namespace
+
+INTERCEPTOR_WINAPI(DWORD, NtWaitForWorkViaWorkerFactory, DWORD a, DWORD b) {
+ // NtWaitForWorkViaWorkerFactory is called from system worker pool threads to
+ // query work scheduled by BindIoCompletionCallback, QueueUserWorkItem, etc.
+ // System worker pool threads are created at arbitraty point in time and
+ // without using CreateThread, so we wrap NtWaitForWorkViaWorkerFactory
+ // instead and don't register a specific parent_tid/stack.
+ EnsureWorkerThreadRegistered();
+ return REAL(NtWaitForWorkViaWorkerFactory)(a, b);
+}
+
+// }}}
+
namespace __asan {
-// ---------------------- TSD ---------------- {{{1
+void InitializePlatformInterceptors() {
+ ASAN_INTERCEPT_FUNC(CreateThread);
+ ASAN_INTERCEPT_FUNC(RaiseException);
+ ASAN_INTERCEPT_FUNC(_except_handler3);
+ ASAN_INTERCEPT_FUNC(_except_handler4);
+
+ // NtWaitForWorkViaWorkerFactory is always linked dynamically.
+ CHECK(::__interception::OverrideFunction(
+ "NtWaitForWorkViaWorkerFactory",
+ (uptr)WRAP(NtWaitForWorkViaWorkerFactory),
+ (uptr *)&REAL(NtWaitForWorkViaWorkerFactory)));
+}
+
+// ---------------------- TSD ---------------- {{{
static bool tsd_key_inited = false;
static __declspec(thread) void *fake_tsd = 0;
@@ -74,7 +172,9 @@ void AsanTSDSet(void *tsd) {
void PlatformTSDDtor(void *tsd) {
AsanThread::TSDDtor(tsd);
}
-// ---------------------- Various stuff ---------------- {{{1
+// }}}
+
+// ---------------------- Various stuff ---------------- {{{
void DisableReexec() {
// No need to re-exec on Windows.
}
@@ -108,23 +208,6 @@ void AsanOnSIGSEGV(int, void *siginfo, void *context) {
static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
-SignalContext SignalContext::Create(void *siginfo, void *context) {
- EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD*)siginfo;
- CONTEXT *context_record = (CONTEXT*)context;
-
- uptr pc = (uptr)exception_record->ExceptionAddress;
-#ifdef _WIN64
- uptr bp = (uptr)context_record->Rbp;
- uptr sp = (uptr)context_record->Rsp;
-#else
- uptr bp = (uptr)context_record->Ebp;
- uptr sp = (uptr)context_record->Esp;
-#endif
- uptr access_addr = exception_record->ExceptionInformation[1];
-
- return SignalContext(context, access_addr, pc, sp, bp);
-}
-
static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
CONTEXT *context = info->ContextRecord;
@@ -177,7 +260,7 @@ int __asan_set_seh_filter() {
static __declspec(allocate(".CRT$XIZ"))
int (*__intercept_seh)() = __asan_set_seh_filter;
#endif
-
+// }}}
} // namespace __asan
#endif // _WIN32
diff --git a/lib/asan/asan_win_dll_thunk.cc b/lib/asan/asan_win_dll_thunk.cc
index 7b9430257..0c363fe29 100644
--- a/lib/asan/asan_win_dll_thunk.cc
+++ b/lib/asan/asan_win_dll_thunk.cc
@@ -319,6 +319,8 @@ INTERFACE_FUNCTION(__sanitizer_ptr_cmp)
INTERFACE_FUNCTION(__sanitizer_ptr_sub)
INTERFACE_FUNCTION(__sanitizer_report_error_summary)
INTERFACE_FUNCTION(__sanitizer_reset_coverage)
+INTERFACE_FUNCTION(__sanitizer_get_number_of_counters)
+INTERFACE_FUNCTION(__sanitizer_update_counter_bitset_and_clear_counters)
INTERFACE_FUNCTION(__sanitizer_sandbox_on_notify)
INTERFACE_FUNCTION(__sanitizer_set_death_callback)
INTERFACE_FUNCTION(__sanitizer_set_report_path)
diff --git a/lib/asan/asan_win_dynamic_runtime_thunk.cc b/lib/asan/asan_win_dynamic_runtime_thunk.cc
index 19456141c..d59f9f576 100644
--- a/lib/asan/asan_win_dynamic_runtime_thunk.cc
+++ b/lib/asan/asan_win_dynamic_runtime_thunk.cc
@@ -15,7 +15,8 @@
//
// This includes:
// - forwarding the detect_stack_use_after_return runtime option
-// - installing a custom SEH handler
+// - working around deficiencies of the MD runtime
+// - installing a custom SEH handlerx
//
//===----------------------------------------------------------------------===//
@@ -24,9 +25,13 @@
// simplifies the build procedure.
#ifdef ASAN_DYNAMIC_RUNTIME_THUNK
#include <windows.h>
-#include <psapi.h>
-extern "C" {
+// First, declare CRT sections we'll be using in this file
+#pragma section(".CRT$XID", long, read) // NOLINT
+#pragma section(".CRT$XIZ", long, read) // NOLINT
+#pragma section(".CRT$XTW", long, read) // NOLINT
+#pragma section(".CRT$XTY", long, read) // NOLINT
+
////////////////////////////////////////////////////////////////////////////////
// Define a copy of __asan_option_detect_stack_use_after_return that should be
// used when linking an MD runtime with a set of object files on Windows.
@@ -38,82 +43,55 @@ extern "C" {
// with a MT or MD runtime and we don't want to use ugly __imp_ names on Windows
// just to work around this issue, let's clone the a variable that is
// constant after initialization anyways.
+extern "C" {
__declspec(dllimport) int __asan_should_detect_stack_use_after_return();
int __asan_option_detect_stack_use_after_return =
__asan_should_detect_stack_use_after_return();
}
////////////////////////////////////////////////////////////////////////////////
-// For some reason, the MD CRT doesn't call the C/C++ terminators as MT does.
-// To work around this, for each DLL we schedule a call to
-// UnregisterGlobalsInRange atexit() specifying the address range of the DLL
-// image to unregister globals in that range. We don't do the same
-// for the main module (.exe) as the asan_globals.cc allocator is destroyed
-// by the time UnregisterGlobalsInRange is executed.
-// See PR22545 for the details.
-namespace __asan {
-__declspec(dllimport)
-void UnregisterGlobalsInRange(void *beg, void *end);
-}
+// For some reason, the MD CRT doesn't call the C/C++ terminators during on DLL
+// unload or on exit. ASan relies on LLVM global_dtors to call
+// __asan_unregister_globals on these events, which unfortunately doesn't work
+// with the MD runtime, see PR22545 for the details.
+// To work around this, for each DLL we schedule a call to UnregisterGlobals
+// using atexit() that calls a small subset of C terminators
+// where LLVM global_dtors is placed. Fingers crossed, no other C terminators
+// are there.
+extern "C" void __cdecl _initterm(void *a, void *b);
namespace {
-void *this_module_base, *this_module_end;
+__declspec(allocate(".CRT$XTW")) void* before_global_dtors = 0;
+__declspec(allocate(".CRT$XTY")) void* after_global_dtors = 0;
void UnregisterGlobals() {
- __asan::UnregisterGlobalsInRange(this_module_base, this_module_end);
+ _initterm(&before_global_dtors, &after_global_dtors);
}
int ScheduleUnregisterGlobals() {
- HMODULE this_module = 0;
- // Increments the reference counter of the DLL module, so need to call
- // FreeLibrary later.
- if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
- (LPCTSTR)&UnregisterGlobals, &this_module))
- return 1;
-
- // Skip the main module.
- if (this_module == GetModuleHandle(0))
- return 0;
-
- MODULEINFO mi;
- bool success =
- GetModuleInformation(GetCurrentProcess(), this_module, &mi, sizeof(mi));
- if (!FreeLibrary(this_module))
- return 2;
- if (!success)
- return 3;
-
- this_module_base = mi.lpBaseOfDll;
- this_module_end = (char*)mi.lpBaseOfDll + mi.SizeOfImage;
-
return atexit(UnregisterGlobals);
}
-} // namespace
-
-///////////////////////////////////////////////////////////////////////////////
-// ASan SEH handling.
-extern "C" __declspec(dllimport) int __asan_set_seh_filter();
-static int SetSEHFilter() { return __asan_set_seh_filter(); }
-///////////////////////////////////////////////////////////////////////////////
-// We schedule some work at start-up by placing callbacks to our code to the
-// list of CRT C initializers.
-//
-// First, declare sections we'll be using:
-#pragma section(".CRT$XID", long, read) // NOLINT
-#pragma section(".CRT$XIZ", long, read) // NOLINT
-
-// We need to call 'atexit(UnregisterGlobals);' after atexit() is initialized
-// (.CRT$XIC) but before the C++ constructors (.CRT$XCA).
+// We need to call 'atexit(UnregisterGlobals);' as early as possible, but after
+// atexit() is initialized (.CRT$XIC). As this is executed before C++
+// initializers (think ctors for globals), UnregisterGlobals gets executed after
+// dtors for C++ globals.
__declspec(allocate(".CRT$XID"))
-static int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals;
+int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals;
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// ASan SEH handling.
// We need to set the ASan-specific SEH handler at the end of CRT initialization
// of each module (see also asan_win.cc).
-//
+extern "C" {
+__declspec(dllimport) int __asan_set_seh_filter();
+static int SetSEHFilter() { return __asan_set_seh_filter(); }
+
// Unfortunately, putting a pointer to __asan_set_seh_filter into
// __asan_intercept_seh gets optimized out, so we have to use an extra function.
-extern "C" __declspec(allocate(".CRT$XIZ"))
-int (*__asan_seh_interceptor)() = SetSEHFilter;
+__declspec(allocate(".CRT$XIZ")) int (*__asan_seh_interceptor)() = SetSEHFilter;
+}
#endif // ASAN_DYNAMIC_RUNTIME_THUNK
diff --git a/lib/asan/scripts/asan_symbolize.py b/lib/asan/scripts/asan_symbolize.py
index 59fceaaed..b9d3ad3ad 100755
--- a/lib/asan/scripts/asan_symbolize.py
+++ b/lib/asan/scripts/asan_symbolize.py
@@ -23,6 +23,7 @@ sysroot_path = None
binary_name_filter = None
fix_filename_patterns = None
logfile = sys.stdin
+allow_system_symbolizer = True
# FIXME: merge the code that calls fix_filename().
def fix_filename(file_name):
@@ -392,6 +393,8 @@ class SymbolizationLoop(object):
[BreakpadSymbolizerFactory(binary), self.llvm_symbolizers[binary]])
result = symbolizers[binary].symbolize(addr, binary, offset)
if result is None:
+ if not allow_system_symbolizer:
+ raise Exception('Failed to launch or use llvm-symbolizer.')
# Initialize system symbolizer only if other symbolizers failed.
symbolizers[binary].append_symbolizer(
SystemSymbolizerFactory(self.system, addr, binary))
diff --git a/lib/asan/tests/asan_asm_test.cc b/lib/asan/tests/asan_asm_test.cc
index 1d8b04d61..200de2c13 100644
--- a/lib/asan/tests/asan_asm_test.cc
+++ b/lib/asan/tests/asan_asm_test.cc
@@ -232,7 +232,7 @@ TEST(AddressSanitizer, asm_flags) {
long magic = 0x1234;
long r = 0x0;
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(__ILP32__)
__asm__("xorq %%rax, %%rax \n\t"
"movq (%[p]), %%rax \n\t"
"sete %%al \n\t"
@@ -248,7 +248,7 @@ TEST(AddressSanitizer, asm_flags) {
: [r] "=r"(r)
: [p] "r"(&magic)
: "eax", "memory");
-#endif // defined(__x86_64__)
+#endif // defined(__x86_64__) && !defined(__ILP32__)
ASSERT_EQ(0x1, r);
}
diff --git a/lib/asan/tests/asan_test.cc b/lib/asan/tests/asan_test.cc
index 952b05e21..aa0808054 100644
--- a/lib/asan/tests/asan_test.cc
+++ b/lib/asan/tests/asan_test.cc
@@ -31,13 +31,13 @@ NOINLINE void free_aaa(void *p) { free_bbb(p); break_optimization(0);}
template<typename T>
NOINLINE void uaf_test(int size, int off) {
- char *p = (char *)malloc_aaa(size);
+ void *p = malloc_aaa(size);
free_aaa(p);
for (int i = 1; i < 100; i++)
free_aaa(malloc_aaa(i));
fprintf(stderr, "writing %ld byte(s) at %p with offset %d\n",
(long)sizeof(T), p, off);
- asan_write((T*)(p + off));
+ asan_write((T *)((char *)p + off));
}
TEST(AddressSanitizer, HasFeatureAddressSanitizerTest) {
@@ -436,10 +436,10 @@ TEST(AddressSanitizer, WrongFreeTest) {
void DoubleFree() {
int *x = (int*)malloc(100 * sizeof(int));
- fprintf(stderr, "DoubleFree: x=%p\n", x);
+ fprintf(stderr, "DoubleFree: x=%p\n", (void *)x);
free(x);
free(x);
- fprintf(stderr, "should have failed in the second free(%p)\n", x);
+ fprintf(stderr, "should have failed in the second free(%p)\n", (void *)x);
abort();
}
@@ -569,7 +569,7 @@ TEST(AddressSanitizer, LongJmpTest) {
}
#if !defined(_WIN32) // Only basic longjmp is available on Windows.
-NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) {
+NOINLINE void UnderscopeLongJmpFunc1(jmp_buf buf) {
// create three red zones for these two stack objects.
int a;
int b;
@@ -577,10 +577,10 @@ NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) {
int *A = Ident(&a);
int *B = Ident(&b);
*A = *B;
- __builtin_longjmp((void**)buf, 1);
+ _longjmp(buf, 1);
}
-NOINLINE void UnderscopeLongJmpFunc1(jmp_buf buf) {
+NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) {
// create three red zones for these two stack objects.
int a;
int b;
@@ -588,10 +588,13 @@ NOINLINE void UnderscopeLongJmpFunc1(jmp_buf buf) {
int *A = Ident(&a);
int *B = Ident(&b);
*A = *B;
- _longjmp(buf, 1);
+ siglongjmp(buf, 1);
}
-NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) {
+#if !defined(__ANDROID__) && !defined(__arm__) && \
+ !defined(__powerpc64__) && !defined(__powerpc__) && \
+ !defined(__aarch64__)
+NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) {
// create three red zones for these two stack objects.
int a;
int b;
@@ -599,12 +602,9 @@ NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) {
int *A = Ident(&a);
int *B = Ident(&b);
*A = *B;
- siglongjmp(buf, 1);
+ __builtin_longjmp((void**)buf, 1);
}
-#if !defined(__ANDROID__) && !defined(__arm__) && \
- !defined(__powerpc64__) && !defined(__powerpc__) && \
- !defined(__aarch64__)
// Does not work on Power and ARM:
// https://code.google.com/p/address-sanitizer/issues/detail?id=185
TEST(AddressSanitizer, BuiltinLongJmpTest) {
@@ -1243,7 +1243,7 @@ TEST(AddressSanitizer, DISABLED_DemoTooMuchMemoryTest) {
const size_t kAllocSize = (1 << 28) - 1024;
size_t total_size = 0;
while (true) {
- char *x = (char*)malloc(kAllocSize);
+ void *x = malloc(kAllocSize);
memset(x, 0, kAllocSize);
total_size += kAllocSize;
fprintf(stderr, "total: %ldM %p\n", (long)total_size >> 20, x);
diff --git a/lib/builtins/clear_cache.c b/lib/builtins/clear_cache.c
index 8dc0fb1c5..ede7659a0 100644
--- a/lib/builtins/clear_cache.c
+++ b/lib/builtins/clear_cache.c
@@ -9,11 +9,12 @@
*/
#include "int_lib.h"
+#include <stddef.h>
#if __APPLE__
#include <libkern/OSCacheControl.h>
#endif
-#if defined(__FreeBSD__) && defined(__arm__)
+#if (defined(__FreeBSD__) || defined(__Bitrig__)) && defined(__arm__)
#include <sys/types.h>
#include <machine/sysarch.h>
#endif
@@ -25,6 +26,7 @@
#if defined(__mips__)
#include <sys/cachectl.h>
#include <sys/syscall.h>
+ #include <unistd.h>
#if defined(__ANDROID__) && defined(__LP64__)
/*
* clear_mips_cache - Invalidates instruction cache for Mips.
@@ -89,7 +91,7 @@ void __clear_cache(void *start, void *end) {
* so there is nothing to do
*/
#elif defined(__arm__) && !defined(__APPLE__)
- #if defined(__FreeBSD__) || defined(__NetBSD__)
+ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__Bitrig__)
struct arm_sync_icache_args arg;
arg.addr = (uintptr_t)start;
@@ -126,6 +128,7 @@ void __clear_cache(void *start, void *end) {
#elif defined(__aarch64__) && !defined(__APPLE__)
uint64_t xstart = (uint64_t)(uintptr_t) start;
uint64_t xend = (uint64_t)(uintptr_t) end;
+ uint64_t addr;
// Get Cache Type Info
uint64_t ctr_el0;
@@ -136,12 +139,12 @@ void __clear_cache(void *start, void *end) {
* uintptr_t in case this runs in an IPL32 environment.
*/
const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15);
- for (uint64_t addr = xstart; addr < xend; addr += dcache_line_size)
+ for (addr = xstart; addr < xend; addr += dcache_line_size)
__asm __volatile("dc cvau, %0" :: "r"(addr));
__asm __volatile("dsb ish");
const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15);
- for (uint64_t addr = xstart; addr < xend; addr += icache_line_size)
+ for (addr = xstart; addr < xend; addr += icache_line_size)
__asm __volatile("ic ivau, %0" :: "r"(addr));
__asm __volatile("isb sy");
#else
diff --git a/lib/builtins/fixdfdi.c b/lib/builtins/fixdfdi.c
index 86f9f6ce8..67b124a16 100644
--- a/lib/builtins/fixdfdi.c
+++ b/lib/builtins/fixdfdi.c
@@ -6,40 +6,17 @@
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
- *
- * This file implements __fixdfdi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
*/
-#include "int_lib.h"
-
-/* Returns: convert a to a signed long long, rounding toward zero. */
-
-/* Assumption: double is a IEEE 64 bit floating point type
- * su_int is a 32 bit integral type
- * value in double is representable in di_int (no range checking performed)
- */
-
-/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
-
+#define DOUBLE_PRECISION
+#include "fp_lib.h"
ARM_EABI_FNALIAS(d2lz, fixdfdi)
+typedef di_int fixint_t;
+typedef du_int fixuint_t;
+#include "fp_fixint_impl.inc"
+
COMPILER_RT_ABI di_int
-__fixdfdi(double a)
-{
- double_bits fb;
- fb.f = a;
- int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
- if (e < 0)
- return 0;
- di_int s = (si_int)(fb.u.s.high & 0x80000000) >> 31;
- dwords r;
- r.s.high = (fb.u.s.high & 0x000FFFFF) | 0x00100000;
- r.s.low = fb.u.s.low;
- if (e > 52)
- r.all <<= (e - 52);
- else
- r.all >>= (52 - e);
- return (r.all ^ s) - s;
-}
+__fixdfdi(fp_t a) {
+ return __fixint(a);
+}
diff --git a/lib/builtins/fixdfsi.c b/lib/builtins/fixdfsi.c
index 88b2ff5e7..704e65bc4 100644
--- a/lib/builtins/fixdfsi.c
+++ b/lib/builtins/fixdfsi.c
@@ -1,50 +1,22 @@
-//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements double-precision to integer conversion for the
-// compiler-rt library. No range checking is performed; the behavior of this
-// conversion is undefined for out of range values in the C standard.
-//
-//===----------------------------------------------------------------------===//
+/* ===-- fixdfsi.c - Implement __fixdfsi -----------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ */
#define DOUBLE_PRECISION
#include "fp_lib.h"
-
-#include "int_lib.h"
+typedef si_int fixint_t;
+typedef su_int fixuint_t;
+#include "fp_fixint_impl.inc"
ARM_EABI_FNALIAS(d2iz, fixdfsi)
-COMPILER_RT_ABI int
+COMPILER_RT_ABI si_int
__fixdfsi(fp_t a) {
-
- // Break a into sign, exponent, significand
- const rep_t aRep = toRep(a);
- const rep_t aAbs = aRep & absMask;
- const int sign = aRep & signBit ? -1 : 1;
- const int exponent = (aAbs >> significandBits) - exponentBias;
- const rep_t significand = (aAbs & significandMask) | implicitBit;
-
- // If 0 < exponent < significandBits, right shift to get the result.
- if ((unsigned int)exponent < significandBits) {
- return sign * (significand >> (significandBits - exponent));
- }
-
- // If exponent is negative, the result is zero.
- else if (exponent < 0) {
- return 0;
- }
-
- // If significandBits < exponent, left shift to get the result. This shift
- // may end up being larger than the type width, which incurs undefined
- // behavior, but the conversion itself is undefined in that case, so
- // whatever the compiler decides to do is fine.
- else {
- return sign * (significand << (exponent - significandBits));
- }
+ return __fixint(a);
}
diff --git a/lib/builtins/fixdfti.c b/lib/builtins/fixdfti.c
index 2c27f4bae..aaf225e74 100644
--- a/lib/builtins/fixdfti.c
+++ b/lib/builtins/fixdfti.c
@@ -6,40 +6,21 @@
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
- *
- * This file implements __fixdfti for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
*/
#include "int_lib.h"
#ifdef CRT_HAS_128BIT
+#define DOUBLE_PRECISION
+#include "fp_lib.h"
-/* Returns: convert a to a signed long long, rounding toward zero. */
-
-/* Assumption: double is a IEEE 64 bit floating point type
- * su_int is a 32 bit integral type
- * value in double is representable in ti_int (no range checking performed)
- */
-
-/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
+typedef ti_int fixint_t;
+typedef tu_int fixuint_t;
+#include "fp_fixint_impl.inc"
COMPILER_RT_ABI ti_int
-__fixdfti(double a)
-{
- double_bits fb;
- fb.f = a;
- int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
- if (e < 0)
- return 0;
- ti_int s = (si_int)(fb.u.s.high & 0x80000000) >> 31;
- ti_int r = 0x0010000000000000uLL | (0x000FFFFFFFFFFFFFuLL & fb.u.all);
- if (e > 52)
- r <<= (e - 52);
- else
- r >>= (52 - e);
- return (r ^ s) - s;
+__fixdfti(fp_t a) {
+ return __fixint(a);
}
#endif /* CRT_HAS_128BIT */
diff --git a/lib/builtins/fixsfdi.c b/lib/builtins/fixsfdi.c
index 4f6cfdd7a..835ff852d 100644
--- a/lib/builtins/fixsfdi.c
+++ b/lib/builtins/fixsfdi.c
@@ -1,43 +1,23 @@
/* ===-- fixsfdi.c - Implement __fixsfdi -----------------------------------===
*
- * The LLVM Compiler Infrastructure
+ * The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
- *
- * This file implements __fixsfdi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
- */
-
-#include "int_lib.h"
-
-/* Returns: convert a to a signed long long, rounding toward zero. */
-
-/* Assumption: float is a IEEE 32 bit floating point type
- * su_int is a 32 bit integral type
- * value in float is representable in di_int (no range checking performed)
*/
-/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
+#define SINGLE_PRECISION
+#include "fp_lib.h"
ARM_EABI_FNALIAS(f2lz, fixsfdi)
+typedef di_int fixint_t;
+typedef du_int fixuint_t;
+#include "fp_fixint_impl.inc"
+
COMPILER_RT_ABI di_int
-__fixsfdi(float a)
-{
- float_bits fb;
- fb.f = a;
- int e = ((fb.u & 0x7F800000) >> 23) - 127;
- if (e < 0)
- return 0;
- di_int s = (si_int)(fb.u & 0x80000000) >> 31;
- di_int r = (fb.u & 0x007FFFFF) | 0x00800000;
- if (e > 23)
- r <<= (e - 23);
- else
- r >>= (23 - e);
- return (r ^ s) - s;
+__fixsfdi(fp_t a) {
+ return __fixint(a);
}
diff --git a/lib/builtins/fixsfsi.c b/lib/builtins/fixsfsi.c
index e3cc42d52..f045536d6 100644
--- a/lib/builtins/fixsfsi.c
+++ b/lib/builtins/fixsfsi.c
@@ -1,47 +1,22 @@
-//===-- lib/fixsfsi.c - Single-precision -> integer conversion ----*- C -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements single-precision to integer conversion for the
-// compiler-rt library. No range checking is performed; the behavior of this
-// conversion is undefined for out of range values in the C standard.
-//
-//===----------------------------------------------------------------------===//
+/* ===-- fixsfsi.c - Implement __fixsfsi -----------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ */
#define SINGLE_PRECISION
#include "fp_lib.h"
+typedef si_int fixint_t;
+typedef su_int fixuint_t;
+#include "fp_fixint_impl.inc"
ARM_EABI_FNALIAS(f2iz, fixsfsi)
-COMPILER_RT_ABI int
+COMPILER_RT_ABI si_int
__fixsfsi(fp_t a) {
- // Break a into sign, exponent, significand
- const rep_t aRep = toRep(a);
- const rep_t aAbs = aRep & absMask;
- const int sign = aRep & signBit ? -1 : 1;
- const int exponent = (aAbs >> significandBits) - exponentBias;
- const rep_t significand = (aAbs & significandMask) | implicitBit;
-
- // If 0 < exponent < significandBits, right shift to get the result.
- if ((unsigned int)exponent < significandBits) {
- return sign * (significand >> (significandBits - exponent));
- }
-
- // If exponent is negative, the result is zero.
- else if (exponent < 0) {
- return 0;
- }
-
- // If significandBits < exponent, left shift to get the result. This shift
- // may end up being larger than the type width, which incurs undefined
- // behavior, but the conversion itself is undefined in that case, so
- // whatever the compiler decides to do is fine.
- else {
- return sign * (significand << (exponent - significandBits));
- }
+ return __fixint(a);
}
diff --git a/lib/builtins/fixsfti.c b/lib/builtins/fixsfti.c
index 6a1a1c6d5..3a159b3e1 100644
--- a/lib/builtins/fixsfti.c
+++ b/lib/builtins/fixsfti.c
@@ -6,40 +6,21 @@
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
- *
- * This file implements __fixsfti for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
*/
#include "int_lib.h"
#ifdef CRT_HAS_128BIT
+#define SINGLE_PRECISION
+#include "fp_lib.h"
-/* Returns: convert a to a signed long long, rounding toward zero. */
-
-/* Assumption: float is a IEEE 32 bit floating point type
- * su_int is a 32 bit integral type
- * value in float is representable in ti_int (no range checking performed)
- */
-
-/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
+typedef ti_int fixint_t;
+typedef tu_int fixuint_t;
+#include "fp_fixint_impl.inc"
COMPILER_RT_ABI ti_int
-__fixsfti(float a)
-{
- float_bits fb;
- fb.f = a;
- int e = ((fb.u & 0x7F800000) >> 23) - 127;
- if (e < 0)
- return 0;
- ti_int s = (si_int)(fb.u & 0x80000000) >> 31;
- ti_int r = (fb.u & 0x007FFFFF) | 0x00800000;
- if (e > 23)
- r <<= (e - 23);
- else
- r >>= (23 - e);
- return (r ^ s) - s;
+__fixsfti(fp_t a) {
+ return __fixint(a);
}
#endif /* CRT_HAS_128BIT */
diff --git a/lib/builtins/fixtfdi.c b/lib/builtins/fixtfdi.c
new file mode 100644
index 000000000..bc9dea1f4
--- /dev/null
+++ b/lib/builtins/fixtfdi.c
@@ -0,0 +1,23 @@
+/* ===-- fixtfdi.c - Implement __fixtfdi -----------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#define QUAD_PRECISION
+#include "fp_lib.h"
+
+#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
+typedef di_int fixint_t;
+typedef du_int fixuint_t;
+#include "fp_fixint_impl.inc"
+
+COMPILER_RT_ABI di_int
+__fixtfdi(fp_t a) {
+ return __fixint(a);
+}
+#endif
diff --git a/lib/builtins/fixtfsi.c b/lib/builtins/fixtfsi.c
new file mode 100644
index 000000000..feb3de885
--- /dev/null
+++ b/lib/builtins/fixtfsi.c
@@ -0,0 +1,23 @@
+/* ===-- fixtfsi.c - Implement __fixtfsi -----------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#define QUAD_PRECISION
+#include "fp_lib.h"
+
+#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
+typedef si_int fixint_t;
+typedef su_int fixuint_t;
+#include "fp_fixint_impl.inc"
+
+COMPILER_RT_ABI si_int
+__fixtfsi(fp_t a) {
+ return __fixint(a);
+}
+#endif
diff --git a/lib/builtins/fixtfti.c b/lib/builtins/fixtfti.c
new file mode 100644
index 000000000..ee4ada85c
--- /dev/null
+++ b/lib/builtins/fixtfti.c
@@ -0,0 +1,23 @@
+/* ===-- fixtfti.c - Implement __fixtfti -----------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#define QUAD_PRECISION
+#include "fp_lib.h"
+
+#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
+typedef ti_int fixint_t;
+typedef tu_int fixuint_t;
+#include "fp_fixint_impl.inc"
+
+COMPILER_RT_ABI ti_int
+__fixtfti(fp_t a) {
+ return __fixint(a);
+}
+#endif
diff --git a/lib/builtins/fixunsdfdi.c b/lib/builtins/fixunsdfdi.c
index 9e6371390..f4f689e39 100644
--- a/lib/builtins/fixunsdfdi.c
+++ b/lib/builtins/fixunsdfdi.c
@@ -6,42 +6,16 @@
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
- *
- * This file implements __fixunsdfdi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
- */
-
-#include "int_lib.h"
-
-/* Returns: convert a to a unsigned long long, rounding toward zero.
- * Negative values all become zero.
- */
-
-/* Assumption: double is a IEEE 64 bit floating point type
- * du_int is a 64 bit integral type
- * value in double is representable in du_int or is negative
- * (no range checking performed)
*/
-/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
+#define DOUBLE_PRECISION
+#include "fp_lib.h"
+typedef du_int fixuint_t;
+#include "fp_fixuint_impl.inc"
ARM_EABI_FNALIAS(d2ulz, fixunsdfdi)
COMPILER_RT_ABI du_int
-__fixunsdfdi(double a)
-{
- double_bits fb;
- fb.f = a;
- int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
- if (e < 0 || (fb.u.s.high & 0x80000000))
- return 0;
- udwords r;
- r.s.high = (fb.u.s.high & 0x000FFFFF) | 0x00100000;
- r.s.low = fb.u.s.low;
- if (e > 52)
- r.all <<= (e - 52);
- else
- r.all >>= (52 - e);
- return r.all;
+__fixunsdfdi(fp_t a) {
+ return __fixuint(a);
}
diff --git a/lib/builtins/fixunsdfsi.c b/lib/builtins/fixunsdfsi.c
index c6a3c755e..232d342d7 100644
--- a/lib/builtins/fixunsdfsi.c
+++ b/lib/builtins/fixunsdfsi.c
@@ -6,39 +6,16 @@
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
- *
- * This file implements __fixunsdfsi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
- */
-
-#include "int_lib.h"
-
-/* Returns: convert a to a unsigned int, rounding toward zero.
- * Negative values all become zero.
- */
-
-/* Assumption: double is a IEEE 64 bit floating point type
- * su_int is a 32 bit integral type
- * value in double is representable in su_int or is negative
- * (no range checking performed)
*/
-/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
+#define DOUBLE_PRECISION
+#include "fp_lib.h"
+typedef su_int fixuint_t;
+#include "fp_fixuint_impl.inc"
ARM_EABI_FNALIAS(d2uiz, fixunsdfsi)
COMPILER_RT_ABI su_int
-__fixunsdfsi(double a)
-{
- double_bits fb;
- fb.f = a;
- int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
- if (e < 0 || (fb.u.s.high & 0x80000000))
- return 0;
- return (
- 0x80000000u |
- ((fb.u.s.high & 0x000FFFFF) << 11) |
- (fb.u.s.low >> 21)
- ) >> (31 - e);
+__fixunsdfsi(fp_t a) {
+ return __fixuint(a);
}
diff --git a/lib/builtins/fixunsdfti.c b/lib/builtins/fixunsdfti.c
index cc6c84ff5..c3d7df97f 100644
--- a/lib/builtins/fixunsdfti.c
+++ b/lib/builtins/fixunsdfti.c
@@ -6,42 +6,18 @@
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
- *
- * This file implements __fixunsdfti for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
*/
#include "int_lib.h"
#ifdef CRT_HAS_128BIT
-
-/* Returns: convert a to a unsigned long long, rounding toward zero.
- * Negative values all become zero.
- */
-
-/* Assumption: double is a IEEE 64 bit floating point type
- * tu_int is a 64 bit integral type
- * value in double is representable in tu_int or is negative
- * (no range checking performed)
- */
-
-/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
+#define DOUBLE_PRECISION
+#include "fp_lib.h"
+typedef tu_int fixuint_t;
+#include "fp_fixuint_impl.inc"
COMPILER_RT_ABI tu_int
-__fixunsdfti(double a)
-{
- double_bits fb;
- fb.f = a;
- int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
- if (e < 0 || (fb.u.s.high & 0x80000000))
- return 0;
- tu_int r = 0x0010000000000000uLL | (fb.u.all & 0x000FFFFFFFFFFFFFuLL);
- if (e > 52)
- r <<= (e - 52);
- else
- r >>= (52 - e);
- return r;
+__fixunsdftti(fp_t a) {
+ return __fixuint(a);
}
-
#endif /* CRT_HAS_128BIT */
diff --git a/lib/builtins/fixunssfdi.c b/lib/builtins/fixunssfdi.c
index 69d5952e9..cd21cfd18 100644
--- a/lib/builtins/fixunssfdi.c
+++ b/lib/builtins/fixunssfdi.c
@@ -6,39 +6,16 @@
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
- *
- * This file implements __fixunssfdi for the compiler_rt library.
- *
- * ===----------------------------------------------------------------------===
- */
-
-#include "int_lib.h"
-/* Returns: convert a to a unsigned long long, rounding toward zero.
- * Negative values all become zero.
- */
-
-/* Assumption: float is a IEEE 32 bit floating point type
- * du_int is a 64 bit integral type
- * value in float is representable in du_int or is negative
- * (no range checking performed)
*/
-/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
+#define SINGLE_PRECISION
+#include "fp_lib.h"
+typedef du_int fixuint_t;
+#include "fp_fixuint_impl.inc"
ARM_EABI_FNALIAS(f2ulz, fixunssfdi)
COMPILER_RT_ABI du_int
-__fixunssfdi(float a)
-{
- float_bits fb;
- fb.f = a;
- int e = ((fb.u & 0x7F800000) >> 23) - 127;
- if (e < 0 || (fb.u & 0x80000000))
- return 0;
- du_int r = (fb.u & 0x007FFFFF) | 0x00800000;
- if (e > 23)
- r <<= (e - 23);
- else
- r >>= (23 - e);
- return r;
+__fixunssfdi(fp_t a) {
+ return __fixuint(a);
}
diff --git a/lib/builtins/fixunssfsi.c b/lib/builtins/fixunssfsi.c
index e034139ea..cc2b05bd8 100644
--- a/lib/builtins/fixunssfsi.c
+++ b/lib/builtins/fixunssfsi.c
@@ -12,34 +12,14 @@
* ===----------------------------------------------------------------------===
*/
-#include "int_lib.h"
-
-/* Returns: convert a to a unsigned int, rounding toward zero.
- * Negative values all become zero.
- */
-
-/* Assumption: float is a IEEE 32 bit floating point type
- * su_int is a 32 bit integral type
- * value in float is representable in su_int or is negative
- * (no range checking performed)
- */
-
-/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
+#define SINGLE_PRECISION
+#include "fp_lib.h"
+typedef su_int fixuint_t;
+#include "fp_fixuint_impl.inc"
ARM_EABI_FNALIAS(f2uiz, fixunssfsi)
COMPILER_RT_ABI su_int
-__fixunssfsi(float a)
-{
- float_bits fb;
- fb.f = a;
- int e = ((fb.u & 0x7F800000) >> 23) - 127;
- if (e < 0 || (fb.u & 0x80000000))
- return 0;
- su_int r = (fb.u & 0x007FFFFF) | 0x00800000;
- if (e > 23)
- r <<= (e - 23);
- else
- r >>= (23 - e);
- return r;
+__fixunssfsi(fp_t a) {
+ return __fixuint(a);
}
diff --git a/lib/builtins/fixunssfti.c b/lib/builtins/fixunssfti.c
index 4da9e242a..862d7bd6c 100644
--- a/lib/builtins/fixunssfti.c
+++ b/lib/builtins/fixunssfti.c
@@ -12,36 +12,15 @@
* ===----------------------------------------------------------------------===
*/
-#include "int_lib.h"
+#define SINGLE_PRECISION
+#include "fp_lib.h"
-#ifdef CRT_HAS_128BIT
-
-/* Returns: convert a to a unsigned long long, rounding toward zero.
- * Negative values all become zero.
- */
-
-/* Assumption: float is a IEEE 32 bit floating point type
- * tu_int is a 64 bit integral type
- * value in float is representable in tu_int or is negative
- * (no range checking performed)
- */
-
-/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
+#if defined(CRT_HAS_128BIT)
+typedef tu_int fixuint_t;
+#include "fp_fixuint_impl.inc"
COMPILER_RT_ABI tu_int
-__fixunssfti(float a)
-{
- float_bits fb;
- fb.f = a;
- int e = ((fb.u & 0x7F800000) >> 23) - 127;
- if (e < 0 || (fb.u & 0x80000000))
- return 0;
- tu_int r = (fb.u & 0x007FFFFF) | 0x00800000;
- if (e > 23)
- r <<= (e - 23);
- else
- r >>= (23 - e);
- return r;
+__fixunssfti(fp_t a) {
+ return __fixuint(a);
}
-
-#endif /* CRT_HAS_128BIT */
+#endif
diff --git a/lib/builtins/fixunstfdi.c b/lib/builtins/fixunstfdi.c
new file mode 100644
index 000000000..b2995f658
--- /dev/null
+++ b/lib/builtins/fixunstfdi.c
@@ -0,0 +1,22 @@
+/* ===-- fixunstfdi.c - Implement __fixunstfdi -----------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#define QUAD_PRECISION
+#include "fp_lib.h"
+
+#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
+typedef du_int fixuint_t;
+#include "fp_fixuint_impl.inc"
+
+COMPILER_RT_ABI du_int
+__fixunstfdi(fp_t a) {
+ return __fixuint(a);
+}
+#endif
diff --git a/lib/builtins/fixunstfsi.c b/lib/builtins/fixunstfsi.c
new file mode 100644
index 000000000..b5d3f6a7d
--- /dev/null
+++ b/lib/builtins/fixunstfsi.c
@@ -0,0 +1,22 @@
+/* ===-- fixunstfsi.c - Implement __fixunstfsi -----------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#define QUAD_PRECISION
+#include "fp_lib.h"
+
+#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
+typedef su_int fixuint_t;
+#include "fp_fixuint_impl.inc"
+
+COMPILER_RT_ABI su_int
+__fixunstfsi(fp_t a) {
+ return __fixuint(a);
+}
+#endif
diff --git a/lib/builtins/fixunstfti.c b/lib/builtins/fixunstfti.c
new file mode 100644
index 000000000..22ff9dfc0
--- /dev/null
+++ b/lib/builtins/fixunstfti.c
@@ -0,0 +1,22 @@
+/* ===-- fixunstfsi.c - Implement __fixunstfsi -----------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#define QUAD_PRECISION
+#include "fp_lib.h"
+
+#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
+typedef tu_int fixuint_t;
+#include "fp_fixuint_impl.inc"
+
+COMPILER_RT_ABI tu_int
+__fixunstfti(fp_t a) {
+ return __fixuint(a);
+}
+#endif
diff --git a/lib/builtins/fixunsxfdi.c b/lib/builtins/fixunsxfdi.c
index 7224d467e..075304e78 100644
--- a/lib/builtins/fixunsxfdi.c
+++ b/lib/builtins/fixunsxfdi.c
@@ -38,6 +38,8 @@ __fixunsxfdi(long double a)
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
if (e < 0 || (fb.u.high.s.low & 0x00008000))
return 0;
+ if ((unsigned)e > sizeof(du_int) * CHAR_BIT)
+ return ~(du_int)0;
return fb.u.low.all >> (63 - e);
}
diff --git a/lib/builtins/fixunsxfsi.c b/lib/builtins/fixunsxfsi.c
index df0a18e2c..c3c70f743 100644
--- a/lib/builtins/fixunsxfsi.c
+++ b/lib/builtins/fixunsxfsi.c
@@ -23,7 +23,6 @@
/* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
* su_int is a 32 bit integral type
* value in long double is representable in su_int or is negative
- * (no range checking performed)
*/
/* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee |
@@ -38,6 +37,8 @@ __fixunsxfsi(long double a)
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
if (e < 0 || (fb.u.high.s.low & 0x00008000))
return 0;
+ if ((unsigned)e > sizeof(su_int) * CHAR_BIT)
+ return ~(su_int)0;
return fb.u.low.s.high >> (31 - e);
}
diff --git a/lib/builtins/fixunsxfti.c b/lib/builtins/fixunsxfti.c
index 42e507304..fb39d00ff 100644
--- a/lib/builtins/fixunsxfti.c
+++ b/lib/builtins/fixunsxfti.c
@@ -21,9 +21,8 @@
*/
/* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
- * tu_int is a 64 bit integral type
+ * tu_int is a 128 bit integral type
* value in long double is representable in tu_int or is negative
- * (no range checking performed)
*/
/* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee |
@@ -38,6 +37,8 @@ __fixunsxfti(long double a)
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
if (e < 0 || (fb.u.high.s.low & 0x00008000))
return 0;
+ if ((unsigned)e > sizeof(tu_int) * CHAR_BIT)
+ return ~(tu_int)0;
tu_int r = fb.u.low.all;
if (e > 63)
r <<= (e - 63);
diff --git a/lib/builtins/fixxfdi.c b/lib/builtins/fixxfdi.c
index afc79d866..011787f9e 100644
--- a/lib/builtins/fixxfdi.c
+++ b/lib/builtins/fixxfdi.c
@@ -19,7 +19,7 @@
/* Returns: convert a to a signed long long, rounding toward zero. */
/* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
- * su_int is a 32 bit integral type
+ * di_int is a 64 bit integral type
* value in long double is representable in di_int (no range checking performed)
*/
@@ -30,11 +30,15 @@
COMPILER_RT_ABI di_int
__fixxfdi(long double a)
{
+ const di_int di_max = (di_int)((~(du_int)0) / 2);
+ const di_int di_min = -di_max - 1;
long_double_bits fb;
fb.f = a;
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
if (e < 0)
return 0;
+ if ((unsigned)e >= sizeof(di_int) * CHAR_BIT)
+ return a > 0 ? di_max : di_min;
di_int s = -(si_int)((fb.u.high.s.low & 0x00008000) >> 15);
di_int r = fb.u.low.all;
r = (du_int)r >> (63 - e);
diff --git a/lib/builtins/fixxfti.c b/lib/builtins/fixxfti.c
index 3d0a279b3..968a4f0d5 100644
--- a/lib/builtins/fixxfti.c
+++ b/lib/builtins/fixxfti.c
@@ -19,8 +19,8 @@
/* Returns: convert a to a signed long long, rounding toward zero. */
/* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
- * su_int is a 32 bit integral type
- * value in long double is representable in ti_int (no range checking performed)
+ * ti_int is a 128 bit integral type
+ * value in long double is representable in ti_int
*/
/* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee |
@@ -30,6 +30,8 @@
COMPILER_RT_ABI ti_int
__fixxfti(long double a)
{
+ const ti_int ti_max = (ti_int)((~(tu_int)0) / 2);
+ const ti_int ti_min = -ti_max - 1;
long_double_bits fb;
fb.f = a;
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
@@ -37,6 +39,8 @@ __fixxfti(long double a)
return 0;
ti_int s = -(si_int)((fb.u.high.s.low & 0x00008000) >> 15);
ti_int r = fb.u.low.all;
+ if ((unsigned)e >= sizeof(ti_int) * CHAR_BIT)
+ return a > 0 ? ti_max : ti_min;
if (e > 63)
r <<= (e - 63);
else
diff --git a/lib/builtins/fp_fixint_impl.inc b/lib/builtins/fp_fixint_impl.inc
new file mode 100644
index 000000000..035e87ca1
--- /dev/null
+++ b/lib/builtins/fp_fixint_impl.inc
@@ -0,0 +1,41 @@
+//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements float to integer conversion for the
+// compiler-rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "fp_lib.h"
+
+static inline fixint_t __fixint(fp_t a) {
+ const fixint_t fixint_max = (fixint_t)((~(fixuint_t)0) / 2);
+ const fixint_t fixint_min = -fixint_max - 1;
+ // Break a into sign, exponent, significand
+ const rep_t aRep = toRep(a);
+ const rep_t aAbs = aRep & absMask;
+ const fixint_t sign = aRep & signBit ? -1 : 1;
+ const int exponent = (aAbs >> significandBits) - exponentBias;
+ const rep_t significand = (aAbs & significandMask) | implicitBit;
+
+ // If exponent is negative, the result is zero.
+ if (exponent < 0)
+ return 0;
+
+ // If the value is too large for the integer type, saturate.
+ if ((unsigned)exponent >= sizeof(fixint_t) * CHAR_BIT)
+ return sign == 1 ? fixint_max : fixint_min;
+
+ // If 0 <= exponent < significandBits, right shift to get the result.
+ // Otherwise, shift left.
+ if (exponent < significandBits)
+ return sign * (significand >> (significandBits - exponent));
+ else
+ return sign * ((fixint_t)significand << (exponent - significandBits));
+}
diff --git a/lib/builtins/fp_fixuint_impl.inc b/lib/builtins/fp_fixuint_impl.inc
new file mode 100644
index 000000000..5fefab0e2
--- /dev/null
+++ b/lib/builtins/fp_fixuint_impl.inc
@@ -0,0 +1,39 @@
+//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements float to unsigned integer conversion for the
+// compiler-rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "fp_lib.h"
+
+static inline fixuint_t __fixuint(fp_t a) {
+ // Break a into sign, exponent, significand
+ const rep_t aRep = toRep(a);
+ const rep_t aAbs = aRep & absMask;
+ const int sign = aRep & signBit ? -1 : 1;
+ const int exponent = (aAbs >> significandBits) - exponentBias;
+ const rep_t significand = (aAbs & significandMask) | implicitBit;
+
+ // If either the value or the exponent is negative, the result is zero.
+ if (sign == -1 || exponent < 0)
+ return 0;
+
+ // If the value is too large for the integer type, saturate.
+ if ((unsigned)exponent > sizeof(fixuint_t) * CHAR_BIT)
+ return ~(fixuint_t)0;
+
+ // If 0 <= exponent < significandBits, right shift to get the result.
+ // Otherwise, shift left.
+ if (exponent < significandBits)
+ return significand >> (significandBits - exponent);
+ else
+ return (fixuint_t)significand << (exponent - significandBits);
+}
diff --git a/lib/dfsan/dfsan.cc b/lib/dfsan/dfsan.cc
index de5b2ce10..5a8da3867 100644
--- a/lib/dfsan/dfsan.cc
+++ b/lib/dfsan/dfsan.cc
@@ -333,7 +333,7 @@ static void InitializeFlags() {
static void dfsan_fini() {
if (internal_strcmp(flags().dump_labels_at_exit, "") != 0) {
- fd_t fd = OpenFile(flags().dump_labels_at_exit, true /* write */);
+ fd_t fd = OpenFile(flags().dump_labels_at_exit, WrOnly);
if (fd == kInvalidFd) {
Report("WARNING: DataFlowSanitizer: unable to open output file %s\n",
flags().dump_labels_at_exit);
diff --git a/lib/interception/interception.h b/lib/interception/interception.h
index 52573258b..9e9aca215 100644
--- a/lib/interception/interception.h
+++ b/lib/interception/interception.h
@@ -219,7 +219,6 @@ const interpose_substitution substitution_##func_name[] \
namespace __interception { \
FUNC_TYPE(func) PTR_TO_REAL(func); \
} \
- DECLARE_WRAPPER_WINAPI(ret_type, func, __VA_ARGS__) \
extern "C" \
INTERCEPTOR_ATTRIBUTE \
ret_type __stdcall WRAP(func)(__VA_ARGS__)
diff --git a/lib/interception/interception_win.cc b/lib/interception/interception_win.cc
index cd241c3d2..19cf18494 100644
--- a/lib/interception/interception_win.cc
+++ b/lib/interception/interception_win.cc
@@ -84,6 +84,7 @@ static size_t RoundUpToInstrBoundary(size_t size, char *code) {
cursor += 2;
continue;
case '\xE9': // E9 XX YY ZZ WW = jmp WWZZYYXX
+ case '\xB8': // B8 XX YY ZZ WW = mov eax, WWZZYYXX
cursor += 5;
continue;
}
@@ -182,10 +183,14 @@ bool OverrideFunction(uptr old_func, uptr new_func, uptr *orig_old_func) {
}
static const void **InterestingDLLsAvailable() {
- const char *InterestingDLLs[] = {"kernel32.dll",
- "msvcr110.dll", // VS2012
- "msvcr120.dll", // VS2013
- NULL};
+ const char *InterestingDLLs[] = {
+ "kernel32.dll",
+ "msvcr110.dll", // VS2012
+ "msvcr120.dll", // VS2013
+ // NTDLL should go last as it exports some functions that we should override
+ // in the CRT [presumably only used internally].
+ "ntdll.dll", NULL
+ };
static void *result[ARRAY_SIZE(InterestingDLLs)] = { 0 };
if (!result[0]) {
for (size_t i = 0, j = 0; InterestingDLLs[i]; ++i) {
diff --git a/lib/lsan/lsan_common.cc b/lib/lsan/lsan_common.cc
index a6119af8d..8ac2ae066 100644
--- a/lib/lsan/lsan_common.cc
+++ b/lib/lsan/lsan_common.cc
@@ -435,13 +435,11 @@ static Suppression *GetSuppressionForAddr(uptr addr) {
Suppression *s = nullptr;
// Suppress by module name.
- const char *module_name;
- uptr module_offset;
SuppressionContext *suppressions = GetSuppressionContext();
- if (Symbolizer::GetOrInit()->GetModuleNameAndOffsetForPC(addr, &module_name,
- &module_offset) &&
- suppressions->Match(module_name, kSuppressionLeak, &s))
- return s;
+ if (const char *module_name =
+ Symbolizer::GetOrInit()->GetModuleNameForPc(addr))
+ if (suppressions->Match(module_name, kSuppressionLeak, &s))
+ return s;
// Suppress by file or function name.
SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(addr);
diff --git a/lib/msan/tests/CMakeLists.txt b/lib/msan/tests/CMakeLists.txt
index e008bd329..4bc825481 100644
--- a/lib/msan/tests/CMakeLists.txt
+++ b/lib/msan/tests/CMakeLists.txt
@@ -33,6 +33,7 @@ set(MSAN_UNITTEST_COMMON_CFLAGS
-Wno-deprecated-declarations
-Wno-unused-variable
-Wno-zero-length-array
+ -Wno-uninitialized
-Werror=sign-compare
)
set(MSAN_UNITTEST_INSTRUMENTED_CFLAGS
diff --git a/lib/profile/InstrProfilingFile.c b/lib/profile/InstrProfilingFile.c
index daa309427..d9acbbeb1 100644
--- a/lib/profile/InstrProfilingFile.c
+++ b/lib/profile/InstrProfilingFile.c
@@ -8,10 +8,10 @@
\*===----------------------------------------------------------------------===*/
#include "InstrProfiling.h"
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/errno.h>
#define UNCONST(ptr) ((void *)(uintptr_t)(ptr))
diff --git a/lib/sanitizer_common/CMakeLists.txt b/lib/sanitizer_common/CMakeLists.txt
index 6eb6ca8fc..5b32b6ad9 100644
--- a/lib/sanitizer_common/CMakeLists.txt
+++ b/lib/sanitizer_common/CMakeLists.txt
@@ -27,6 +27,7 @@ set(SANITIZER_SOURCES
sanitizer_suppressions.cc
sanitizer_symbolizer.cc
sanitizer_symbolizer_libbacktrace.cc
+ sanitizer_symbolizer_mac.cc
sanitizer_symbolizer_win.cc
sanitizer_tls_get_addr.cc
sanitizer_thread_registry.cc
@@ -42,6 +43,7 @@ set(SANITIZER_LIBCDEP_SOURCES
sanitizer_stoptheworld_linux_libcdep.cc
sanitizer_symbolizer_libcdep.cc
sanitizer_symbolizer_posix_libcdep.cc
+ sanitizer_symbolizer_process_libcdep.cc
sanitizer_unwind_posix_libcdep.cc)
# Explicitly list all sanitizer_common headers. Not all of these are
@@ -91,7 +93,10 @@ set(SANITIZER_HEADERS
sanitizer_stoptheworld.h
sanitizer_suppressions.h
sanitizer_symbolizer.h
+ sanitizer_symbolizer_internal.h
sanitizer_symbolizer_libbacktrace.h
+ sanitizer_symbolizer_mac.h
+ sanitizer_symbolizer_win.h
sanitizer_syscall_generic.inc
sanitizer_syscall_linux_x86_64.inc
sanitizer_thread_registry.h)
@@ -137,12 +142,6 @@ else()
DEFS ${SANITIZER_COMMON_DEFINITIONS})
list(APPEND SANITIZER_RUNTIME_LIBRARIES RTSanitizerCommon.${arch}
RTSanitizerCommonLibc.${arch})
- add_compiler_rt_runtime(clang_rt.san-${arch} ${arch} STATIC
- SOURCES $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
- $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
- CFLAGS ${SANITIZER_CFLAGS}
- DEFS ${SANITIZER_COMMON_DEFINITIONS})
- add_dependencies(sanitizer_common clang_rt.san-${arch})
endforeach()
endif()
diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc
index 4be3c7abf..956fc9935 100644
--- a/lib/sanitizer_common/sanitizer_common.cc
+++ b/lib/sanitizer_common/sanitizer_common.cc
@@ -16,6 +16,8 @@
#include "sanitizer_flags.h"
#include "sanitizer_libc.h"
#include "sanitizer_placement_new.h"
+#include "sanitizer_stacktrace_printer.h"
+#include "sanitizer_symbolizer.h"
namespace __sanitizer {
@@ -56,7 +58,7 @@ void ReportFile::ReopenIfNecessary() {
}
internal_snprintf(full_path, kMaxPathLength, "%s.%zu", path_prefix, pid);
- uptr openrv = OpenFile(full_path, true);
+ uptr openrv = OpenFile(full_path, WrOnly);
if (internal_iserror(openrv)) {
const char *ErrorMsgPrefix = "ERROR: Can't open file: ";
internal_write(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
@@ -142,7 +144,7 @@ uptr ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
*buff_size = 0;
// The files we usually open are not seekable, so try different buffer sizes.
for (uptr size = kMinFileLen; size <= max_len; size *= 2) {
- uptr openrv = OpenFile(file_name, /*write*/ false);
+ uptr openrv = OpenFile(file_name, RdOnly);
if (internal_iserror(openrv, errno_p)) return 0;
fd_t fd = openrv;
UnmapOrDie(*buff, *buff_size);
@@ -206,12 +208,12 @@ const char *StripPathPrefix(const char *filepath,
const char *strip_path_prefix) {
if (filepath == 0) return 0;
if (strip_path_prefix == 0) return filepath;
- const char *pos = internal_strstr(filepath, strip_path_prefix);
- if (pos == 0) return filepath;
- pos += internal_strlen(strip_path_prefix);
- if (pos[0] == '.' && pos[1] == '/')
- pos += 2;
- return pos;
+ const char *res = filepath;
+ if (const char *pos = internal_strstr(filepath, strip_path_prefix))
+ res = pos + internal_strlen(strip_path_prefix);
+ if (res[0] == '.' && res[1] == '/')
+ res += 2;
+ return res;
}
const char *StripModuleName(const char *module) {
@@ -230,17 +232,16 @@ void ReportErrorSummary(const char *error_message) {
__sanitizer_report_error_summary(buff.data());
}
-void ReportErrorSummary(const char *error_type, const char *file,
- int line, const char *function) {
+#ifndef SANITIZER_GO
+void ReportErrorSummary(const char *error_type, const AddressInfo &info) {
if (!common_flags()->print_summary)
return;
InternalScopedString buff(kMaxSummaryLength);
- buff.append("%s %s:%d %s", error_type,
- file ? StripPathPrefix(file, common_flags()->strip_path_prefix)
- : "??",
- line, function ? function : "??");
+ buff.append("%s ", error_type);
+ RenderFrame(&buff, "%L %F", 0, info, common_flags()->strip_path_prefix);
ReportErrorSummary(buff.data());
}
+#endif
LoadedModule::LoadedModule(const char *module_name, uptr base_address) {
full_name_ = internal_strdup(module_name);
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h
index ff13ef164..0dfa81593 100644
--- a/lib/sanitizer_common/sanitizer_common.h
+++ b/lib/sanitizer_common/sanitizer_common.h
@@ -25,6 +25,7 @@
namespace __sanitizer {
struct StackTrace;
+struct AddressInfo;
// Constants.
const uptr kWordSize = SANITIZER_WORDSIZE / 8;
@@ -186,7 +187,13 @@ extern ReportFile report_file;
extern uptr stoptheworld_tracer_pid;
extern uptr stoptheworld_tracer_ppid;
-uptr OpenFile(const char *filename, bool write);
+enum FileAccessMode {
+ RdOnly,
+ WrOnly,
+ RdWr
+};
+
+uptr OpenFile(const char *filename, FileAccessMode mode);
// Opens the file 'file_name" and reads up to 'max_len' bytes.
// The resulting buffer is mmaped and stored in '*buff'.
// The size of the mmaped region is stored in '*buff_size',
@@ -215,6 +222,11 @@ const char *GetEnv(const char *name);
bool SetEnv(const char *name, const char *value);
const char *GetPwd();
char *FindPathToBinary(const char *name);
+bool IsPathSeparator(const char c);
+bool IsAbsolutePath(const char *path);
+
+// Returns the path to the main executable.
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
u32 GetUid();
void ReExec();
bool StackSizeIsUnlimited();
@@ -288,9 +300,9 @@ const int kMaxSummaryLength = 1024;
// and pass it to __sanitizer_report_error_summary.
void ReportErrorSummary(const char *error_message);
// Same as above, but construct error_message as:
-// error_type file:line function
-void ReportErrorSummary(const char *error_type, const char *file,
- int line, const char *function);
+// error_type file:line[:column][ function]
+void ReportErrorSummary(const char *error_type, const AddressInfo &info);
+// Same as above, but obtains AddressInfo by symbolizing top stack trace frame.
void ReportErrorSummary(const char *error_type, StackTrace *trace);
// Math
@@ -439,11 +451,15 @@ class InternalMmapVectorNoCtor {
const T *data() const {
return data_;
}
+ T *data() {
+ return data_;
+ }
uptr capacity() const {
return capacity_;
}
void clear() { size_ = 0; }
+ bool empty() const { return size() == 0; }
private:
void Resize(uptr new_capacity) {
@@ -532,6 +548,7 @@ uptr InternalBinarySearch(const Container &v, uptr first, uptr last,
// executable or a shared object).
class LoadedModule {
public:
+ LoadedModule() : full_name_(nullptr), base_address_(0) {}
LoadedModule(const char *module_name, uptr base_address);
void clear();
void addAddressRange(uptr beg, uptr end, bool executable);
@@ -607,6 +624,23 @@ static inline void SanitizerBreakOptimization(void *arg) {
#endif
}
+struct SignalContext {
+ void *context;
+ uptr addr;
+ uptr pc;
+ uptr sp;
+ uptr bp;
+
+ SignalContext(void *context, uptr addr, uptr pc, uptr sp, uptr bp) :
+ context(context), addr(addr), pc(pc), sp(sp), bp(bp) {
+ }
+
+ // Creates signal context in a platform-specific manner.
+ static SignalContext Create(void *siginfo, void *context);
+};
+
+void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);
+
} // namespace __sanitizer
inline void *operator new(__sanitizer::operator_new_size_type size,
diff --git a/lib/sanitizer_common/sanitizer_common_libcdep.cc b/lib/sanitizer_common/sanitizer_common_libcdep.cc
index 17ef6897b..9622e60c2 100644
--- a/lib/sanitizer_common/sanitizer_common_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_common_libcdep.cc
@@ -44,20 +44,16 @@ void SetSandboxingCallback(void (*f)()) {
void ReportErrorSummary(const char *error_type, StackTrace *stack) {
if (!common_flags()->print_summary)
return;
-#if !SANITIZER_GO
- if (stack->size > 0 && Symbolizer::GetOrInit()->CanReturnFileLineInfo()) {
- // Currently, we include the first stack frame into the report summary.
- // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
- uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
- SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
- const AddressInfo &ai = frame->info;
- ReportErrorSummary(error_type, ai.file, ai.line, ai.function);
- frame->ClearAll();
+ if (stack->size == 0) {
+ ReportErrorSummary(error_type);
+ return;
}
-#else
- AddressInfo ai;
- ReportErrorSummary(error_type, ai.file, ai.line, ai.function);
-#endif
+ // Currently, we include the first stack frame into the report summary.
+ // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
+ uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
+ SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
+ ReportErrorSummary(error_type, frame->info);
+ frame->ClearAll();
}
static void (*SoftRssLimitExceededCallback)(bool exceeded);
diff --git a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
index 49887b1e9..94863c6ef 100644
--- a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
@@ -24,8 +24,12 @@
// and atomically set Guard to -Guard.
// - __sanitizer_cov_dump: dump the coverage data to disk.
// For every module of the current process that has coverage data
-// this will create a file module_name.PID.sancov. The file format is simple:
-// it's just a sorted sequence of 4-byte offsets in the module.
+// this will create a file module_name.PID.sancov.
+//
+// The file format is simple: the first 8 bytes is the magic,
+// one of 0xC0BFFFFFFFFFFF64 and 0xC0BFFFFFFFFFFF32. The last byte of the
+// magic defines the size of the following offsets.
+// The rest of the data is the offsets in the module.
//
// Eventually, this coverage implementation should be obsoleted by a more
// powerful general purpose Clang/LLVM coverage instrumentation.
@@ -43,6 +47,9 @@
#include "sanitizer_symbolizer.h"
#include "sanitizer_flags.h"
+static const u64 kMagic64 = 0xC0BFFFFFFFFFFF64ULL;
+static const u64 kMagic32 = 0xC0BFFFFFFFFFFF32ULL;
+
static atomic_uint32_t dump_once_guard; // Ensure that CovDump runs only once.
static atomic_uintptr_t coverage_counter;
@@ -77,21 +84,32 @@ class CoverageData {
uptr cache_size);
void DumpCallerCalleePairs();
void DumpTrace();
+ void DumpAsBitSet();
+ void DumpCounters();
+ void DumpOffsets();
+ void DumpAll();
ALWAYS_INLINE
void TraceBasicBlock(s32 *id);
void InitializeGuardArray(s32 *guards);
- void InitializeGuards(s32 *guards, uptr n, const char *module_name);
+ void InitializeGuards(s32 *guards, uptr n, const char *module_name,
+ uptr caller_pc);
+ void InitializeCounters(u8 *counters, uptr n);
void ReinitializeGuards();
+ uptr GetNumberOf8bitCounters();
+ uptr Update8bitCounterBitsetAndClearCounters(u8 *bitset);
uptr *data();
uptr size();
private:
+ void DirectOpen();
+ void UpdateModuleNameVec(uptr caller_pc, uptr range_beg, uptr range_end);
+
// Maximal size pc array may ever grow.
// We MmapNoReserve this space to ensure that the array is contiguous.
- static const uptr kPcArrayMaxSize = FIRST_32_SECOND_64(1 << 24, 1 << 27);
+ static const uptr kPcArrayMaxSize = FIRST_32_SECOND_64(1 << 26, 1 << 27);
// The amount file mapping for the pc array is grown by.
static const uptr kPcArrayMmapSize = 64 * 1024;
@@ -110,8 +128,22 @@ class CoverageData {
// Vector of coverage guard arrays, protected by mu.
InternalMmapVectorNoCtor<s32*> guard_array_vec;
- // Vector of module (compilation unit) names.
- InternalMmapVectorNoCtor<const char*> comp_unit_name_vec;
+ struct NamedPcRange {
+ const char *copied_module_name;
+ uptr beg, end; // elements [beg,end) in pc_array.
+ };
+
+ // Vector of module and compilation unit pc ranges.
+ InternalMmapVectorNoCtor<NamedPcRange> comp_unit_name_vec;
+ InternalMmapVectorNoCtor<NamedPcRange> module_name_vec;
+
+ struct CounterAndSize {
+ u8 *counters;
+ uptr n;
+ };
+
+ InternalMmapVectorNoCtor<CounterAndSize> counters_vec;
+ uptr num_8bit_counters;
// Caller-Callee (cc) array, size and current index.
static const uptr kCcArrayMaxSize = FIRST_32_SECOND_64(1 << 18, 1 << 24);
@@ -133,8 +165,6 @@ class CoverageData {
static const uptr kTrPcArrayMaxSize = FIRST_32_SECOND_64(1 << 22, 1 << 27);
StaticSpinMutex mu;
-
- void DirectOpen();
};
static CoverageData coverage_data;
@@ -145,9 +175,9 @@ void CoverageData::DirectOpen() {
InternalScopedString path(kMaxPathLength);
internal_snprintf((char *)path.data(), path.size(), "%s/%zd.sancov.raw",
coverage_dir, internal_getpid());
- pc_fd = OpenFile(path.data(), true);
+ pc_fd = OpenFile(path.data(), RdWr);
if (internal_iserror(pc_fd)) {
- Report(" Coverage: failed to open %s for writing\n", path.data());
+ Report(" Coverage: failed to open %s for reading/writing\n", path.data());
Die();
}
@@ -184,6 +214,8 @@ void CoverageData::Enable() {
GetMmapGranularity());
tr_event_array_size = kTrEventArrayMaxSize;
tr_event_pointer = tr_event_array;
+
+ num_8bit_counters = 0;
}
void CoverageData::InitializeGuardArray(s32 *guards) {
@@ -289,16 +321,70 @@ void CoverageData::Extend(uptr npcs) {
atomic_store(&pc_array_size, size, memory_order_release);
}
+void CoverageData::InitializeCounters(u8 *counters, uptr n) {
+ if (!counters) return;
+ CHECK_EQ(reinterpret_cast<uptr>(counters) % 16, 0);
+ n = RoundUpTo(n, 16); // The compiler must ensure that counters is 16-aligned.
+ SpinMutexLock l(&mu);
+ counters_vec.push_back({counters, n});
+ num_8bit_counters += n;
+}
+
+void CoverageData::UpdateModuleNameVec(uptr caller_pc, uptr range_beg,
+ uptr range_end) {
+ auto sym = Symbolizer::GetOrInit();
+ if (!sym)
+ return;
+ const char *module_name = sym->GetModuleNameForPc(caller_pc);
+ if (!module_name) return;
+ if (module_name_vec.empty() ||
+ internal_strcmp(module_name_vec.back().copied_module_name, module_name))
+ module_name_vec.push_back(
+ {internal_strdup(module_name), range_beg, range_end});
+ else
+ module_name_vec.back().end = range_end;
+}
+
void CoverageData::InitializeGuards(s32 *guards, uptr n,
- const char *module_name) {
+ const char *comp_unit_name,
+ uptr caller_pc) {
// The array 'guards' has n+1 elements, we use the element zero
// to store 'n'.
CHECK_LT(n, 1 << 30);
guards[0] = static_cast<s32>(n);
InitializeGuardArray(guards);
SpinMutexLock l(&mu);
- comp_unit_name_vec.push_back(module_name);
+ uptr range_end = atomic_load(&pc_array_index, memory_order_relaxed);
+ uptr range_beg = range_end - n;
+ comp_unit_name_vec.push_back({comp_unit_name, range_beg, range_end});
guard_array_vec.push_back(guards);
+ UpdateModuleNameVec(caller_pc, range_beg, range_end);
+}
+
+static const uptr kBundleCounterBits = 16;
+
+// When coverage_order_pcs==true and SANITIZER_WORDSIZE==64
+// we insert the global counter into the first 16 bits of the PC.
+uptr BundlePcAndCounter(uptr pc, uptr counter) {
+ if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs)
+ return pc;
+ static const uptr kMaxCounter = (1 << kBundleCounterBits) - 1;
+ if (counter > kMaxCounter)
+ counter = kMaxCounter;
+ CHECK_EQ(0, pc >> (SANITIZER_WORDSIZE - kBundleCounterBits));
+ return pc | (counter << (SANITIZER_WORDSIZE - kBundleCounterBits));
+}
+
+uptr UnbundlePc(uptr bundle) {
+ if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs)
+ return bundle;
+ return (bundle << kBundleCounterBits) >> kBundleCounterBits;
+}
+
+uptr UnbundleCounter(uptr bundle) {
+ if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs)
+ return 0;
+ return bundle >> (SANITIZER_WORDSIZE - kBundleCounterBits);
}
// If guard is negative, atomically set it to -guard and store the PC in
@@ -316,8 +402,8 @@ void CoverageData::Add(uptr pc, u32 *guard) {
return; // May happen after fork when pc_array_index becomes 0.
CHECK_LT(idx * sizeof(uptr),
atomic_load(&pc_array_size, memory_order_acquire));
- pc_array[idx] = pc;
- atomic_fetch_add(&coverage_counter, 1, memory_order_relaxed);
+ uptr counter = atomic_fetch_add(&coverage_counter, 1, memory_order_relaxed);
+ pc_array[idx] = BundlePcAndCounter(pc, counter);
}
// Registers a pair caller=>callee.
@@ -354,6 +440,64 @@ void CoverageData::IndirCall(uptr caller, uptr callee, uptr callee_cache[],
}
}
+uptr CoverageData::GetNumberOf8bitCounters() {
+ return num_8bit_counters;
+}
+
+// Map every 8bit counter to a 8-bit bitset and clear the counter.
+uptr CoverageData::Update8bitCounterBitsetAndClearCounters(u8 *bitset) {
+ uptr num_new_bits = 0;
+ uptr cur = 0;
+ // For better speed we map 8 counters to 8 bytes of bitset at once.
+ static const uptr kBatchSize = 8;
+ CHECK_EQ(reinterpret_cast<uptr>(bitset) % kBatchSize, 0);
+ for (uptr i = 0, len = counters_vec.size(); i < len; i++) {
+ u8 *c = counters_vec[i].counters;
+ uptr n = counters_vec[i].n;
+ CHECK_EQ(n % 16, 0);
+ CHECK_EQ(cur % kBatchSize, 0);
+ CHECK_EQ(reinterpret_cast<uptr>(c) % kBatchSize, 0);
+ if (!bitset) {
+ internal_bzero_aligned16(c, n);
+ cur += n;
+ continue;
+ }
+ for (uptr j = 0; j < n; j += kBatchSize, cur += kBatchSize) {
+ CHECK_LT(cur, num_8bit_counters);
+ u64 *pc64 = reinterpret_cast<u64*>(c + j);
+ u64 *pb64 = reinterpret_cast<u64*>(bitset + cur);
+ u64 c64 = *pc64;
+ u64 old_bits_64 = *pb64;
+ u64 new_bits_64 = old_bits_64;
+ if (c64) {
+ *pc64 = 0;
+ for (uptr k = 0; k < kBatchSize; k++) {
+ u64 x = (c64 >> (8 * k)) & 0xff;
+ if (x) {
+ u64 bit = 0;
+ /**/ if (x >= 128) bit = 128;
+ else if (x >= 32) bit = 64;
+ else if (x >= 16) bit = 32;
+ else if (x >= 8) bit = 16;
+ else if (x >= 4) bit = 8;
+ else if (x >= 3) bit = 4;
+ else if (x >= 2) bit = 2;
+ else if (x >= 1) bit = 1;
+ u64 mask = bit << (8 * k);
+ if (!(new_bits_64 & mask)) {
+ num_new_bits++;
+ new_bits_64 |= mask;
+ }
+ }
+ }
+ *pb64 = new_bits_64;
+ }
+ }
+ }
+ CHECK_EQ(cur, num_8bit_counters);
+ return num_new_bits;
+}
+
uptr *CoverageData::data() {
return pc_array;
}
@@ -413,23 +557,23 @@ static void CovWritePacked(int pid, const char *module, const void *blob,
// If packed = true and name == 0: <pid>.<sancov>.<packed>.
// If packed = true and name != 0: <name>.<sancov>.<packed> (name is
// user-supplied).
-static int CovOpenFile(bool packed, const char *name,
- const char *extension = "sancov") {
- InternalScopedString path(kMaxPathLength);
+static int CovOpenFile(InternalScopedString *path, bool packed,
+ const char *name, const char *extension = "sancov") {
+ path->clear();
if (!packed) {
CHECK(name);
- path.append("%s/%s.%zd.%s", coverage_dir, name, internal_getpid(),
+ path->append("%s/%s.%zd.%s", coverage_dir, name, internal_getpid(),
extension);
} else {
if (!name)
- path.append("%s/%zd.%s.packed", coverage_dir, internal_getpid(),
+ path->append("%s/%zd.%s.packed", coverage_dir, internal_getpid(),
extension);
else
- path.append("%s/%s.%s.packed", coverage_dir, name, extension);
+ path->append("%s/%s.%s.packed", coverage_dir, name, extension);
}
- uptr fd = OpenFile(path.data(), true);
+ uptr fd = OpenFile(path->data(), WrOnly);
if (internal_iserror(fd)) {
- Report(" SanitizerCoverage: failed to open %s for writing\n", path.data());
+ Report(" SanitizerCoverage: failed to open %s for writing\n", path->data());
return -1;
}
return fd;
@@ -446,24 +590,25 @@ void CoverageData::DumpTrace() {
for (uptr i = 0, n = size(); i < n; i++) {
const char *module_name = "<unknown>";
uptr module_address = 0;
- sym->GetModuleNameAndOffsetForPC(pc_array[i], &module_name,
+ sym->GetModuleNameAndOffsetForPC(UnbundlePc(pc_array[i]), &module_name,
&module_address);
out.append("%s 0x%zx\n", module_name, module_address);
}
- int fd = CovOpenFile(false, "trace-points");
+ InternalScopedString path(kMaxPathLength);
+ int fd = CovOpenFile(&path, false, "trace-points");
if (fd < 0) return;
internal_write(fd, out.data(), out.length());
internal_close(fd);
- fd = CovOpenFile(false, "trace-compunits");
+ fd = CovOpenFile(&path, false, "trace-compunits");
if (fd < 0) return;
out.clear();
for (uptr i = 0; i < comp_unit_name_vec.size(); i++)
- out.append("%s\n", comp_unit_name_vec[i]);
+ out.append("%s\n", comp_unit_name_vec[i].copied_module_name);
internal_write(fd, out.data(), out.length());
internal_close(fd);
- fd = CovOpenFile(false, "trace-events");
+ fd = CovOpenFile(&path, false, "trace-events");
if (fd < 0) return;
uptr bytes_to_write = max_idx * sizeof(tr_event_array[0]);
u8 *event_bytes = reinterpret_cast<u8*>(tr_event_array);
@@ -514,7 +659,8 @@ void CoverageData::DumpCallerCalleePairs() {
callee_module_address);
}
}
- int fd = CovOpenFile(false, "caller-callee");
+ InternalScopedString path(kMaxPathLength);
+ int fd = CovOpenFile(&path, false, "caller-callee");
if (fd < 0) return;
internal_write(fd, out.data(), out.length());
internal_close(fd);
@@ -534,86 +680,124 @@ void CoverageData::TraceBasicBlock(s32 *id) {
tr_event_pointer++;
}
-static void CovDumpAsBitSet() {
+void CoverageData::DumpCounters() {
+ if (!common_flags()->coverage_counters) return;
+ uptr n = coverage_data.GetNumberOf8bitCounters();
+ if (!n) return;
+ InternalScopedBuffer<u8> bitset(n);
+ coverage_data.Update8bitCounterBitsetAndClearCounters(bitset.data());
+ InternalScopedString path(kMaxPathLength);
+
+ for (uptr m = 0; m < module_name_vec.size(); m++) {
+ auto r = module_name_vec[m];
+ CHECK(r.copied_module_name);
+ CHECK_LE(r.beg, r.end);
+ CHECK_LE(r.end, size());
+ const char *base_name = StripModuleName(r.copied_module_name);
+ int fd =
+ CovOpenFile(&path, /* packed */ false, base_name, "counters-sancov");
+ if (fd < 0) return;
+ internal_write(fd, bitset.data() + r.beg, r.end - r.beg);
+ internal_close(fd);
+ VReport(1, " CovDump: %zd counters written for '%s'\n", r.end - r.beg,
+ base_name);
+ }
+}
+
+void CoverageData::DumpAsBitSet() {
if (!common_flags()->coverage_bitset) return;
- if (!coverage_data.size()) return;
- int fd = CovOpenFile(/* packed */false, "combined", "bitset-sancov");
- if (fd < 0) return;
- uptr n = coverage_data.size();
- uptr n_set_bits = 0;
- InternalScopedBuffer<char> out(n);
- for (uptr i = 0; i < n; i++) {
- uptr pc = coverage_data.data()[i];
- out[i] = pc ? '1' : '0';
- if (pc)
- n_set_bits++;
+ if (!size()) return;
+ InternalScopedBuffer<char> out(size());
+ InternalScopedString path(kMaxPathLength);
+ for (uptr m = 0; m < module_name_vec.size(); m++) {
+ uptr n_set_bits = 0;
+ auto r = module_name_vec[m];
+ CHECK(r.copied_module_name);
+ CHECK_LE(r.beg, r.end);
+ CHECK_LE(r.end, size());
+ for (uptr i = r.beg; i < r.end; i++) {
+ uptr pc = UnbundlePc(pc_array[i]);
+ out[i] = pc ? '1' : '0';
+ if (pc)
+ n_set_bits++;
+ }
+ const char *base_name = StripModuleName(r.copied_module_name);
+ int fd = CovOpenFile(&path, /* packed */ false, base_name, "bitset-sancov");
+ if (fd < 0) return;
+ internal_write(fd, out.data() + r.beg, r.end - r.beg);
+ internal_close(fd);
+ VReport(1,
+ " CovDump: bitset of %zd bits written for '%s', %zd bits are set\n",
+ r.end - r.beg, base_name, n_set_bits);
}
- internal_write(fd, out.data(), n);
- internal_close(fd);
- VReport(1, " CovDump: bitset of %zd bits written, %zd bits are set\n", n,
- n_set_bits);
}
-// Dump the coverage on disk.
-static void CovDump() {
- if (!coverage_enabled || common_flags()->coverage_direct) return;
-#if !SANITIZER_WINDOWS
- if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed))
- return;
- CovDumpAsBitSet();
- coverage_data.DumpTrace();
+void CoverageData::DumpOffsets() {
+ auto sym = Symbolizer::GetOrInit();
if (!common_flags()->coverage_pcs) return;
- uptr size = coverage_data.size();
- InternalMmapVector<u32> offsets(size);
- uptr *vb = coverage_data.data();
- uptr *ve = vb + size;
- SortArray(vb, size);
- MemoryMappingLayout proc_maps(/*cache_enabled*/true);
- uptr mb, me, off, prot;
- InternalScopedString module(kMaxPathLength);
+ CHECK_NE(sym, nullptr);
+ InternalMmapVector<uptr> offsets(0);
InternalScopedString path(kMaxPathLength);
- for (int i = 0;
- proc_maps.Next(&mb, &me, &off, module.data(), module.size(), &prot);
- i++) {
- if ((prot & MemoryMappingLayout::kProtectionExecute) == 0)
- continue;
- while (vb < ve && *vb < mb) vb++;
- if (vb >= ve) break;
- if (*vb < me) {
- offsets.clear();
- const uptr *old_vb = vb;
- CHECK_LE(off, *vb);
- for (; vb < ve && *vb < me; vb++) {
- uptr diff = *vb - (i ? mb : 0) + off;
- CHECK_LE(diff, 0xffffffffU);
- offsets.push_back(static_cast<u32>(diff));
- }
- const char *module_name = StripModuleName(module.data());
- if (cov_sandboxed) {
- if (cov_fd >= 0) {
- CovWritePacked(internal_getpid(), module_name, offsets.data(),
- offsets.size() * sizeof(u32));
- VReport(1, " CovDump: %zd PCs written to packed file\n", vb - old_vb);
- }
- } else {
- // One file per module per process.
- path.clear();
- path.append("%s/%s.%zd.sancov", coverage_dir, module_name,
- internal_getpid());
- int fd = CovOpenFile(false /* packed */, module_name);
- if (fd > 0) {
- internal_write(fd, offsets.data(), offsets.size() * sizeof(u32));
- internal_close(fd);
- VReport(1, " CovDump: %s: %zd PCs written\n", path.data(),
- vb - old_vb);
- }
+ for (uptr m = 0; m < module_name_vec.size(); m++) {
+ offsets.clear();
+ uptr num_words_for_magic = SANITIZER_WORDSIZE == 64 ? 1 : 2;
+ for (uptr i = 0; i < num_words_for_magic; i++)
+ offsets.push_back(0);
+ auto r = module_name_vec[m];
+ CHECK(r.copied_module_name);
+ CHECK_LE(r.beg, r.end);
+ CHECK_LE(r.end, size());
+ for (uptr i = r.beg; i < r.end; i++) {
+ uptr pc = UnbundlePc(pc_array[i]);
+ uptr counter = UnbundleCounter(pc_array[i]);
+ if (!pc) continue; // Not visited.
+ const char *unused;
+ uptr offset = 0;
+ sym->GetModuleNameAndOffsetForPC(pc, &unused, &offset);
+ offsets.push_back(BundlePcAndCounter(offset, counter));
+ }
+
+ CHECK_GE(offsets.size(), num_words_for_magic);
+ SortArray(offsets.data(), offsets.size());
+ for (uptr i = 0; i < offsets.size(); i++)
+ offsets[i] = UnbundlePc(offsets[i]);
+
+ uptr num_offsets = offsets.size() - num_words_for_magic;
+ u64 *magic_p = reinterpret_cast<u64*>(offsets.data());
+ CHECK_EQ(*magic_p, 0ULL);
+ // FIXME: we may want to write 32-bit offsets even in 64-mode
+ // if all the offsets are small enough.
+ *magic_p = SANITIZER_WORDSIZE == 64 ? kMagic64 : kMagic32;
+
+ const char *module_name = StripModuleName(r.copied_module_name);
+ if (cov_sandboxed) {
+ if (cov_fd >= 0) {
+ CovWritePacked(internal_getpid(), module_name, offsets.data(),
+ offsets.size() * sizeof(offsets[0]));
+ VReport(1, " CovDump: %zd PCs written to packed file\n", num_offsets);
}
+ } else {
+ // One file per module per process.
+ int fd = CovOpenFile(&path, false /* packed */, module_name);
+ if (fd < 0) continue;
+ internal_write(fd, offsets.data(), offsets.size() * sizeof(offsets[0]));
+ internal_close(fd);
+ VReport(1, " CovDump: %s: %zd PCs written\n", path.data(), num_offsets);
}
}
if (cov_fd >= 0)
internal_close(cov_fd);
- coverage_data.DumpCallerCalleePairs();
-#endif // !SANITIZER_WINDOWS
+}
+
+void CoverageData::DumpAll() {
+ if (!coverage_enabled || common_flags()->coverage_direct) return;
+ if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed))
+ return;
+ DumpAsBitSet();
+ DumpCounters();
+ DumpTrace();
+ DumpOffsets();
+ DumpCallerCalleePairs();
}
void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
@@ -623,15 +807,18 @@ void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
if (!cov_sandboxed) return;
cov_fd = args->coverage_fd;
cov_max_block_size = args->coverage_max_block_size;
- if (cov_fd < 0)
+ if (cov_fd < 0) {
+ InternalScopedString path(kMaxPathLength);
// Pre-open the file now. The sandbox won't allow us to do it later.
- cov_fd = CovOpenFile(true /* packed */, 0);
+ cov_fd = CovOpenFile(&path, true /* packed */, 0);
+ }
}
int MaybeOpenCovFile(const char *name) {
CHECK(name);
if (!coverage_enabled) return -1;
- return CovOpenFile(true /* packed */, name);
+ InternalScopedString path(kMaxPathLength);
+ return CovOpenFile(&path, true /* packed */, name);
}
void CovBeforeFork() {
@@ -674,7 +861,8 @@ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(u32 *guard) {
}
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_with_check(u32 *guard) {
atomic_uint32_t *atomic_guard = reinterpret_cast<atomic_uint32_t*>(guard);
- if (__sanitizer::atomic_load(atomic_guard, memory_order_relaxed))
+ if (static_cast<s32>(
+ __sanitizer::atomic_load(atomic_guard, memory_order_relaxed)) < 0)
__sanitizer_cov(guard);
}
SANITIZER_INTERFACE_ATTRIBUTE void
@@ -687,10 +875,14 @@ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init() {
coverage_dir = common_flags()->coverage_dir;
coverage_data.Init();
}
-SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { CovDump(); }
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() {
+ coverage_data.DumpAll();
+}
SANITIZER_INTERFACE_ATTRIBUTE void
-__sanitizer_cov_module_init(s32 *guards, uptr npcs, const char *module_name) {
- coverage_data.InitializeGuards(guards, npcs, module_name);
+__sanitizer_cov_module_init(s32 *guards, uptr npcs, u8 *counters,
+ const char *comp_unit_name) {
+ coverage_data.InitializeGuards(guards, npcs, comp_unit_name, GET_CALLER_PC());
+ coverage_data.InitializeCounters(counters, npcs);
if (!common_flags()->coverage_direct) return;
if (SANITIZER_ANDROID && coverage_enabled) {
// dlopen/dlclose interceptors do not work on Android, so we rely on
@@ -728,4 +920,14 @@ uptr __sanitizer_get_coverage_guards(uptr **data) {
*data = coverage_data.data();
return coverage_data.size();
}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __sanitizer_get_number_of_counters() {
+ return coverage_data.GetNumberOf8bitCounters();
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __sanitizer_update_counter_bitset_and_clear_counters(u8 *bitset) {
+ return coverage_data.Update8bitCounterBitsetAndClearCounters(bitset);
+}
} // extern "C"
diff --git a/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc
index 6b5e91fbc..d3bde4b24 100644
--- a/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc
@@ -102,7 +102,7 @@ void CovUpdateMapping(const char *coverage_dir, uptr caller_pc) {
"%s/%zd.sancov.map.tmp", coverage_dir,
internal_getpid());
CHECK_LE(res, tmp_path.size());
- uptr map_fd = OpenFile(tmp_path.data(), true);
+ uptr map_fd = OpenFile(tmp_path.data(), WrOnly);
if (internal_iserror(map_fd, &err)) {
Report(" Coverage: failed to open %s for writing: %d\n", tmp_path.data(),
err);
diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc
index 58f7f3722..884602f79 100644
--- a/lib/sanitizer_common/sanitizer_flags.inc
+++ b/lib/sanitizer_common/sanitizer_flags.inc
@@ -111,13 +111,18 @@ COMMON_FLAG(
bool, coverage, false,
"If set, coverage information will be dumped at program shutdown (if the "
"coverage instrumentation was enabled at compile time).")
-// On by default, but works only if coverage == true.
COMMON_FLAG(bool, coverage_pcs, true,
"If set (and if 'coverage' is set too), the coverage information "
"will be dumped as a set of PC offsets for every module.")
+COMMON_FLAG(bool, coverage_order_pcs, false,
+ "If true, the PCs will be dumped in the order they've"
+ " appeared during the execution.")
COMMON_FLAG(bool, coverage_bitset, false,
"If set (and if 'coverage' is set too), the coverage information "
"will also be dumped as a bitset to a separate file.")
+COMMON_FLAG(bool, coverage_counters, false,
+ "If set (and if 'coverage' is set too), the bitmap that corresponds"
+ " to coverage counters will be dumped.")
COMMON_FLAG(bool, coverage_direct, SANITIZER_ANDROID,
"If set, coverage information will be dumped directly to a memory "
"mapped file. This way data is not lost even if the process is "
diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc
index 8029181a5..8d2ea4889 100644
--- a/lib/sanitizer_common/sanitizer_linux.cc
+++ b/lib/sanitizer_common/sanitizer_linux.cc
@@ -57,6 +57,7 @@
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <ucontext.h>
#include <unistd.h>
#if SANITIZER_FREEBSD
@@ -147,11 +148,6 @@ uptr internal_open(const char *filename, int flags, u32 mode) {
#endif
}
-uptr OpenFile(const char *filename, bool write) {
- return internal_open(filename,
- write ? O_RDWR | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
-}
-
uptr internal_read(fd_t fd, void *buf, uptr count) {
sptr res;
HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf,
@@ -168,7 +164,8 @@ uptr internal_write(fd_t fd, const void *buf, uptr count) {
uptr internal_ftruncate(fd_t fd, uptr size) {
sptr res;
- HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd, size));
+ HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd,
+ (OFF_T)size));
return res;
}
@@ -558,6 +555,7 @@ int internal_fork() {
}
#if SANITIZER_LINUX
+#define SA_RESTORER 0x04000000
// Doesn't set sa_restorer, use with caution (see below).
int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
__sanitizer_kernel_sigaction_t k_act, k_oldact;
@@ -570,7 +568,8 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
k_act.sigaction = u_act->sigaction;
internal_memcpy(&k_act.sa_mask, &u_act->sa_mask,
sizeof(__sanitizer_kernel_sigset_t));
- k_act.sa_flags = u_act->sa_flags;
+ // Without SA_RESTORER kernel ignores the calls (probably returns EINVAL).
+ k_act.sa_flags = u_act->sa_flags | SA_RESTORER;
// FIXME: most often sa_restorer is unset, however the kernel requires it
// to point to a valid signal restorer that calls the rt_sigreturn syscall.
// If sa_restorer passed to the kernel is NULL, the program may crash upon
@@ -928,6 +927,78 @@ void *internal_start_thread(void (*func)(void *), void *arg) { return 0; }
void internal_join_thread(void *th) {}
#endif
+void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
+#if defined(__arm__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.arm_pc;
+ *bp = ucontext->uc_mcontext.arm_fp;
+ *sp = ucontext->uc_mcontext.arm_sp;
+#elif defined(__aarch64__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.pc;
+ *bp = ucontext->uc_mcontext.regs[29];
+ *sp = ucontext->uc_mcontext.sp;
+#elif defined(__hppa__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.sc_iaoq[0];
+ /* GCC uses %r3 whenever a frame pointer is needed. */
+ *bp = ucontext->uc_mcontext.sc_gr[3];
+ *sp = ucontext->uc_mcontext.sc_gr[30];
+#elif defined(__x86_64__)
+# if SANITIZER_FREEBSD
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.mc_rip;
+ *bp = ucontext->uc_mcontext.mc_rbp;
+ *sp = ucontext->uc_mcontext.mc_rsp;
+# else
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.gregs[REG_RIP];
+ *bp = ucontext->uc_mcontext.gregs[REG_RBP];
+ *sp = ucontext->uc_mcontext.gregs[REG_RSP];
+# endif
+#elif defined(__i386__)
+# if SANITIZER_FREEBSD
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.mc_eip;
+ *bp = ucontext->uc_mcontext.mc_ebp;
+ *sp = ucontext->uc_mcontext.mc_esp;
+# else
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.gregs[REG_EIP];
+ *bp = ucontext->uc_mcontext.gregs[REG_EBP];
+ *sp = ucontext->uc_mcontext.gregs[REG_ESP];
+# endif
+#elif defined(__powerpc__) || defined(__powerpc64__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.regs->nip;
+ *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
+ // The powerpc{,64}-linux ABIs do not specify r31 as the frame
+ // pointer, but GCC always uses r31 when we need a frame pointer.
+ *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
+#elif defined(__sparc__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ uptr *stk_ptr;
+# if defined (__arch64__)
+ *pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
+ *sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
+ stk_ptr = (uptr *) (*sp + 2047);
+ *bp = stk_ptr[15];
+# else
+ *pc = ucontext->uc_mcontext.gregs[REG_PC];
+ *sp = ucontext->uc_mcontext.gregs[REG_O6];
+ stk_ptr = (uptr *) *sp;
+ *bp = stk_ptr[15];
+# endif
+#elif defined(__mips__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.gregs[31];
+ *bp = ucontext->uc_mcontext.gregs[30];
+ *sp = ucontext->uc_mcontext.gregs[29];
+#else
+# error "Unsupported arch"
+#endif
+}
+
} // namespace __sanitizer
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
diff --git a/lib/sanitizer_common/sanitizer_linux.h b/lib/sanitizer_common/sanitizer_linux.h
index b2e603d3a..2ce2025d2 100644
--- a/lib/sanitizer_common/sanitizer_linux.h
+++ b/lib/sanitizer_common/sanitizer_linux.h
@@ -80,8 +80,6 @@ uptr ThreadSelfOffset();
// information).
bool LibraryNameIs(const char *full_name, const char *base_name);
-// Read the name of the current binary from /proc/self/exe.
-uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
// Cache the value of /proc/self/exe.
void CacheBinaryName();
diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc
index c71b6257e..1c099d862 100644
--- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc
@@ -488,7 +488,7 @@ static uptr GetRSSFromGetrusage() {
uptr GetRSS() {
if (!common_flags()->can_use_proc_maps_statm)
return GetRSSFromGetrusage();
- uptr fd = OpenFile("/proc/self/statm", false);
+ uptr fd = OpenFile("/proc/self/statm", RdOnly);
if ((sptr)fd < 0)
return GetRSSFromGetrusage();
char buf[64];
diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc
index 39a5c7e8d..91a5b7d93 100644
--- a/lib/sanitizer_common/sanitizer_mac.cc
+++ b/lib/sanitizer_common/sanitizer_mac.cc
@@ -31,9 +31,11 @@
#include <crt_externs.h> // for _NSGetEnviron
#include <fcntl.h>
+#include <mach-o/dyld.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
+#include <stdlib.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>
@@ -69,11 +71,6 @@ uptr internal_open(const char *filename, int flags, u32 mode) {
return open(filename, flags, mode);
}
-uptr OpenFile(const char *filename, bool write) {
- return internal_open(filename,
- write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
-}
-
uptr internal_read(fd_t fd, void *buf, uptr count) {
return read(fd, buf, count);
}
@@ -204,6 +201,21 @@ const char *GetEnv(const char *name) {
return 0;
}
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
+ CHECK_LE(kMaxPathLength, buf_len);
+
+ // On OS X the executable path is saved to the stack by dyld. Reading it
+ // from there is much faster than calling dladdr, especially for large
+ // binaries with symbols.
+ InternalScopedString exe_path(kMaxPathLength);
+ uint32_t size = exe_path.size();
+ if (_NSGetExecutablePath(exe_path.data(), &size) == 0 &&
+ realpath(exe_path.data(), buf) != 0) {
+ return internal_strlen(buf);
+ }
+ return 0;
+}
+
void ReExec() {
UNIMPLEMENTED();
}
@@ -328,6 +340,19 @@ uptr GetRSS() {
void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; }
void internal_join_thread(void *th) { }
+void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
+ ucontext_t *ucontext = (ucontext_t*)context;
+# if SANITIZER_WORDSIZE == 64
+ *pc = ucontext->uc_mcontext->__ss.__rip;
+ *bp = ucontext->uc_mcontext->__ss.__rbp;
+ *sp = ucontext->uc_mcontext->__ss.__rsp;
+# else
+ *pc = ucontext->uc_mcontext->__ss.__eip;
+ *bp = ucontext->uc_mcontext->__ss.__ebp;
+ *sp = ucontext->uc_mcontext->__ss.__esp;
+# endif // SANITIZER_WORDSIZE
+}
+
} // namespace __sanitizer
#endif // SANITIZER_MAC
diff --git a/lib/sanitizer_common/sanitizer_posix.cc b/lib/sanitizer_common/sanitizer_posix.cc
index 5bc41c258..5e01212c2 100644
--- a/lib/sanitizer_common/sanitizer_posix.cc
+++ b/lib/sanitizer_common/sanitizer_posix.cc
@@ -20,6 +20,8 @@
#include "sanitizer_procmaps.h"
#include "sanitizer_stacktrace.h"
+#include <fcntl.h>
+#include <signal.h>
#include <sys/mman.h>
#if SANITIZER_LINUX
@@ -47,7 +49,7 @@ uptr GetMmapGranularity() {
#if SANITIZER_WORDSIZE == 32
// Take care of unusable kernel area in top gigabyte.
static uptr GetKernelAreaSize() {
-#if SANITIZER_LINUX
+#if SANITIZER_LINUX && !SANITIZER_X32
const uptr gbyte = 1UL << 30;
// Firstly check if there are writable segments
@@ -79,7 +81,7 @@ static uptr GetKernelAreaSize() {
return gbyte;
#else
return 0;
-#endif // SANITIZER_LINUX
+#endif // SANITIZER_LINUX && !SANITIZER_X32
}
#endif // SANITIZER_WORDSIZE == 32
@@ -203,8 +205,18 @@ void *Mprotect(uptr fixed_addr, uptr size) {
MAP_NORESERVE, -1, 0);
}
+uptr OpenFile(const char *filename, FileAccessMode mode) {
+ int flags;
+ switch (mode) {
+ case RdOnly: flags = O_RDONLY; break;
+ case WrOnly: flags = O_WRONLY | O_CREAT; break;
+ case RdWr: flags = O_RDWR | O_CREAT; break;
+ }
+ return internal_open(filename, flags, 0660);
+}
+
void *MapFileToMemory(const char *file_name, uptr *buff_size) {
- uptr openrv = OpenFile(file_name, false);
+ uptr openrv = OpenFile(file_name, RdOnly);
CHECK(!internal_iserror(openrv));
fd_t fd = openrv;
uptr fsize = internal_filesize(fd);
@@ -219,9 +231,10 @@ void *MapWritableFileToMemory(void *addr, uptr size, uptr fd, uptr offset) {
uptr flags = MAP_SHARED;
if (addr) flags |= MAP_FIXED;
uptr p = internal_mmap(addr, size, PROT_READ | PROT_WRITE, flags, fd, offset);
- if (internal_iserror(p)) {
- Printf("could not map writable file (%zd, %zu, %zu): %zd\n", fd, offset,
- size, p);
+ int mmap_errno = 0;
+ if (internal_iserror(p, &mmap_errno)) {
+ Printf("could not map writable file (%zd, %zu, %zu): %zd, errno: %d\n",
+ fd, offset, size, p, mmap_errno);
return 0;
}
return (void *)p;
@@ -293,6 +306,14 @@ char *FindPathToBinary(const char *name) {
return 0;
}
+bool IsPathSeparator(const char c) {
+ return c == '/';
+}
+
+bool IsAbsolutePath(const char *path) {
+ return path != nullptr && IsPathSeparator(path[0]);
+}
+
void ReportFile::Write(const char *buffer, uptr length) {
SpinMutexLock l(mu);
static const char *kWriteError =
@@ -319,6 +340,13 @@ bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) {
return false;
}
+SignalContext SignalContext::Create(void *siginfo, void *context) {
+ uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr;
+ uptr pc, sp, bp;
+ GetPcSpBp(context, &pc, &sp, &bp);
+ return SignalContext(context, addr, pc, sp, bp);
+}
+
} // namespace __sanitizer
#endif // SANITIZER_POSIX
diff --git a/lib/sanitizer_common/sanitizer_stoptheworld.h b/lib/sanitizer_common/sanitizer_stoptheworld.h
index a32646708..aa6f5d833 100644
--- a/lib/sanitizer_common/sanitizer_stoptheworld.h
+++ b/lib/sanitizer_common/sanitizer_stoptheworld.h
@@ -59,7 +59,8 @@ typedef void (*StopTheWorldCallback)(
// Suspend all threads in the current process and run the callback on the list
// of suspended threads. This function will resume the threads before returning.
-// The callback should not call any libc functions.
+// The callback should not call any libc functions. The callback must not call
+// exit() nor _exit() and instead return to the caller.
// This function should NOT be called from multiple threads simultaneously.
void StopTheWorld(StopTheWorldCallback callback, void *argument);
diff --git a/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
index ad20e3955..64e1c7974 100644
--- a/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
@@ -19,6 +19,7 @@
#include "sanitizer_stoptheworld.h"
#include "sanitizer_platform_limits_posix.h"
+#include "sanitizer_atomic.h"
#include <errno.h>
#include <sched.h> // for CLONE_* definitions
@@ -70,11 +71,25 @@
COMPILER_CHECK(sizeof(SuspendedThreadID) == sizeof(pid_t));
namespace __sanitizer {
+
+// Structure for passing arguments into the tracer thread.
+struct TracerThreadArgument {
+ StopTheWorldCallback callback;
+ void *callback_argument;
+ // The tracer thread waits on this mutex while the parent finishes its
+ // preparations.
+ BlockingMutex mutex;
+ // Tracer thread signals its completion by setting done.
+ atomic_uintptr_t done;
+ uptr parent_pid;
+};
+
// This class handles thread suspending/unsuspending in the tracer thread.
class ThreadSuspender {
public:
- explicit ThreadSuspender(pid_t pid)
- : pid_(pid) {
+ explicit ThreadSuspender(pid_t pid, TracerThreadArgument *arg)
+ : arg(arg)
+ , pid_(pid) {
CHECK_GE(pid, 0);
}
bool SuspendAllThreads();
@@ -83,6 +98,7 @@ class ThreadSuspender {
SuspendedThreadsList &suspended_threads_list() {
return suspended_threads_list_;
}
+ TracerThreadArgument *arg;
private:
SuspendedThreadsList suspended_threads_list_;
pid_t pid_;
@@ -103,7 +119,7 @@ bool ThreadSuspender::SuspendThread(SuspendedThreadID tid) {
VReport(1, "Could not attach to thread %d (errno %d).\n", tid, pterrno);
return false;
} else {
- VReport(1, "Attached to thread %d.\n", tid);
+ VReport(2, "Attached to thread %d.\n", tid);
// The thread is not guaranteed to stop before ptrace returns, so we must
// wait on it. Note: if the thread receives a signal concurrently,
// we can get notification about the signal before notification about stop.
@@ -143,7 +159,7 @@ void ThreadSuspender::ResumeAllThreads() {
int pterrno;
if (!internal_iserror(internal_ptrace(PTRACE_DETACH, tid, NULL, NULL),
&pterrno)) {
- VReport(1, "Detached from thread %d.\n", tid);
+ VReport(2, "Detached from thread %d.\n", tid);
} else {
// Either the thread is dead, or we are already detached.
// The latter case is possible, for instance, if this function was called
@@ -188,25 +204,23 @@ static ThreadSuspender *thread_suspender_instance = NULL;
static const int kSyncSignals[] = { SIGABRT, SIGILL, SIGFPE, SIGSEGV, SIGBUS,
SIGXCPU, SIGXFSZ };
-// Structure for passing arguments into the tracer thread.
-struct TracerThreadArgument {
- StopTheWorldCallback callback;
- void *callback_argument;
- // The tracer thread waits on this mutex while the parent finishes its
- // preparations.
- BlockingMutex mutex;
- uptr parent_pid;
-};
-
static DieCallbackType old_die_callback;
// Signal handler to wake up suspended threads when the tracer thread dies.
-static void TracerThreadSignalHandler(int signum, void *siginfo, void *) {
- if (thread_suspender_instance != NULL) {
+static void TracerThreadSignalHandler(int signum, void *siginfo, void *uctx) {
+ SignalContext ctx = SignalContext::Create(siginfo, uctx);
+ VPrintf(1, "Tracer caught signal %d: addr=0x%zx pc=0x%zx sp=0x%zx\n",
+ signum, ctx.addr, ctx.pc, ctx.sp);
+ ThreadSuspender *inst = thread_suspender_instance;
+ if (inst != NULL) {
if (signum == SIGABRT)
- thread_suspender_instance->KillAllThreads();
+ inst->KillAllThreads();
else
- thread_suspender_instance->ResumeAllThreads();
+ inst->ResumeAllThreads();
+ SetDieCallback(old_die_callback);
+ old_die_callback = NULL;
+ thread_suspender_instance = NULL;
+ atomic_store(&inst->arg->done, 1, memory_order_relaxed);
}
internal__exit((signum == SIGABRT) ? 1 : 2);
}
@@ -218,10 +232,15 @@ static void TracerThreadDieCallback() {
// point. So we correctly handle calls to Die() from within the callback, but
// not those that happen before or after the callback. Hopefully there aren't
// a lot of opportunities for that to happen...
- if (thread_suspender_instance)
- thread_suspender_instance->KillAllThreads();
+ ThreadSuspender *inst = thread_suspender_instance;
+ if (inst != NULL && stoptheworld_tracer_pid == internal_getpid()) {
+ inst->KillAllThreads();
+ thread_suspender_instance = NULL;
+ }
if (old_die_callback)
old_die_callback();
+ SetDieCallback(old_die_callback);
+ old_die_callback = NULL;
}
// Size of alternative stack for signal handlers in the tracer thread.
@@ -244,7 +263,7 @@ static int TracerThread(void* argument) {
old_die_callback = GetDieCallback();
SetDieCallback(TracerThreadDieCallback);
- ThreadSuspender thread_suspender(internal_getppid());
+ ThreadSuspender thread_suspender(internal_getppid(), tracer_thread_argument);
// Global pointer for the signal handler.
thread_suspender_instance = &thread_suspender;
@@ -276,11 +295,9 @@ static int TracerThread(void* argument) {
thread_suspender.ResumeAllThreads();
exit_code = 0;
}
- // Note, this is a bad race. If TracerThreadDieCallback is already started
- // in another thread and observed that thread_suspender_instance != 0,
- // it can call KillAllThreads on the destroyed variable.
SetDieCallback(old_die_callback);
thread_suspender_instance = NULL;
+ atomic_store(&tracer_thread_argument->done, 1, memory_order_relaxed);
return exit_code;
}
@@ -354,6 +371,7 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {
tracer_thread_argument.callback = callback;
tracer_thread_argument.callback_argument = argument;
tracer_thread_argument.parent_pid = internal_getpid();
+ atomic_store(&tracer_thread_argument.done, 0, memory_order_relaxed);
const uptr kTracerStackSize = 2 * 1024 * 1024;
ScopedStackSpaceWithGuard tracer_stack(kTracerStackSize);
// Block the execution of TracerThread until after we have set ptrace
@@ -402,14 +420,27 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {
#endif
// Allow the tracer thread to start.
tracer_thread_argument.mutex.Unlock();
- // Since errno is shared between this thread and the tracer thread, we
- // must avoid using errno while the tracer thread is running.
- // At this point, any signal will either be blocked or kill us, so waitpid
- // should never return (and set errno) while the tracer thread is alive.
- uptr waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL);
- if (internal_iserror(waitpid_status, &local_errno))
+ // NOTE: errno is shared between this thread and the tracer thread.
+ // internal_waitpid() may call syscall() which can access/spoil errno,
+ // so we can't call it now. Instead we for the tracer thread to finish using
+ // the spin loop below. Man page for sched_yield() says "In the Linux
+ // implementation, sched_yield() always succeeds", so let's hope it does not
+ // spoil errno. Note that this spin loop runs only for brief periods before
+ // the tracer thread has suspended us and when it starts unblocking threads.
+ while (atomic_load(&tracer_thread_argument.done, memory_order_relaxed) == 0)
+ sched_yield();
+ // Now the tracer thread is about to exit and does not touch errno,
+ // wait for it.
+ for (;;) {
+ uptr waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL);
+ if (!internal_iserror(waitpid_status, &local_errno))
+ break;
+ if (local_errno == EINTR)
+ continue;
VReport(1, "Waiting on the tracer thread failed (errno %d).\n",
local_errno);
+ break;
+ }
}
}
diff --git a/lib/sanitizer_common/sanitizer_suppressions.cc b/lib/sanitizer_common/sanitizer_suppressions.cc
index 2b697e955..8009b4d6a 100644
--- a/lib/sanitizer_common/sanitizer_suppressions.cc
+++ b/lib/sanitizer_common/sanitizer_suppressions.cc
@@ -30,18 +30,50 @@ SuppressionContext::SuppressionContext(const char *suppression_types[],
internal_memset(has_suppression_type_, 0, suppression_types_num_);
}
+static bool GetPathAssumingFileIsRelativeToExec(const char *file_path,
+ /*out*/char *new_file_path,
+ uptr new_file_path_size) {
+ InternalScopedString exec(kMaxPathLength);
+ if (ReadBinaryName(exec.data(), exec.size())) {
+ const char *file_name_pos = StripModuleName(exec.data());
+ uptr path_to_exec_len = file_name_pos - exec.data();
+ internal_strncat(new_file_path, exec.data(),
+ Min(path_to_exec_len, new_file_path_size - 1));
+ internal_strncat(new_file_path, file_path,
+ new_file_path_size - internal_strlen(new_file_path) - 1);
+ return true;
+ }
+ return false;
+}
+
void SuppressionContext::ParseFromFile(const char *filename) {
if (filename[0] == '\0')
return;
+
+ // If we cannot find the file, check if its location is relative to
+ // the location of the executable.
+ InternalScopedString new_file_path(kMaxPathLength);
+ if (!FileExists(filename) && !IsAbsolutePath(filename) &&
+ GetPathAssumingFileIsRelativeToExec(filename, new_file_path.data(),
+ new_file_path.size())) {
+ filename = new_file_path.data();
+ }
+
+ // Read the file.
char *file_contents;
uptr buffer_size;
- uptr contents_size = ReadFileToBuffer(filename, &file_contents, &buffer_size,
- 1 << 26 /* max_len */);
+ const uptr max_len = 1 << 26;
+ uptr contents_size =
+ ReadFileToBuffer(filename, &file_contents, &buffer_size, max_len);
+ VPrintf(1, "%s: reading suppressions file at %s\n",
+ SanitizerToolName, filename);
+
if (contents_size == 0) {
Printf("%s: failed to read suppressions file '%s'\n", SanitizerToolName,
filename);
Die();
}
+
Parse(file_contents);
}
diff --git a/lib/sanitizer_common/sanitizer_symbolizer.cc b/lib/sanitizer_common/sanitizer_symbolizer.cc
index 135720ed5..df7661ab6 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer.cc
@@ -16,7 +16,7 @@
#include "sanitizer_internal_defs.h"
#include "sanitizer_libc.h"
#include "sanitizer_placement_new.h"
-#include "sanitizer_symbolizer.h"
+#include "sanitizer_symbolizer_internal.h"
namespace __sanitizer {
@@ -33,9 +33,7 @@ void AddressInfo::Clear() {
function_offset = kUnknown;
}
-void AddressInfo::FillAddressAndModuleInfo(uptr addr, const char *mod_name,
- uptr mod_offset) {
- address = addr;
+void AddressInfo::FillModuleInfo(const char *mod_name, uptr mod_offset) {
module = internal_strdup(mod_name);
module_offset = mod_offset;
}
@@ -70,13 +68,6 @@ Symbolizer *Symbolizer::symbolizer_;
StaticSpinMutex Symbolizer::init_mu_;
LowLevelAllocator Symbolizer::symbolizer_allocator_;
-Symbolizer *Symbolizer::Disable() {
- CHECK_EQ(0, symbolizer_);
- // Initialize a dummy symbolizer.
- symbolizer_ = new(symbolizer_allocator_) Symbolizer;
- return symbolizer_;
-}
-
void Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook,
Symbolizer::EndSymbolizationHook end_hook) {
CHECK(start_hook_ == 0 && end_hook_ == 0);
@@ -84,7 +75,8 @@ void Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook,
end_hook_ = end_hook;
}
-Symbolizer::Symbolizer() : start_hook_(0), end_hook_(0) {}
+Symbolizer::Symbolizer(IntrusiveList<SymbolizerTool> tools)
+ : tools_(tools), start_hook_(0), end_hook_(0) {}
Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym)
: sym_(sym) {
@@ -97,4 +89,76 @@ Symbolizer::SymbolizerScope::~SymbolizerScope() {
sym_->end_hook_();
}
+SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
+ BlockingMutexLock l(&mu_);
+ const char *module_name;
+ uptr module_offset;
+ SymbolizedStack *res = SymbolizedStack::New(addr);
+ if (!PlatformFindModuleNameAndOffsetForAddress(addr, &module_name,
+ &module_offset))
+ return res;
+ // Always fill data about module name and offset.
+ res->info.FillModuleInfo(module_name, module_offset);
+ for (auto iter = Iterator(&tools_); iter.hasNext();) {
+ auto *tool = iter.next();
+ SymbolizerScope sym_scope(this);
+ if (tool->SymbolizePC(addr, res)) {
+ return res;
+ }
+ }
+ return res;
+}
+
+bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
+ BlockingMutexLock l(&mu_);
+ const char *module_name;
+ uptr module_offset;
+ if (!PlatformFindModuleNameAndOffsetForAddress(addr, &module_name,
+ &module_offset))
+ return false;
+ info->Clear();
+ info->module = internal_strdup(module_name);
+ info->module_offset = module_offset;
+ for (auto iter = Iterator(&tools_); iter.hasNext();) {
+ auto *tool = iter.next();
+ SymbolizerScope sym_scope(this);
+ if (tool->SymbolizeData(addr, info)) {
+ return true;
+ }
+ }
+ return true;
+}
+
+bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
+ uptr *module_address) {
+ BlockingMutexLock l(&mu_);
+ return PlatformFindModuleNameAndOffsetForAddress(pc, module_name,
+ module_address);
+}
+
+void Symbolizer::Flush() {
+ BlockingMutexLock l(&mu_);
+ for (auto iter = Iterator(&tools_); iter.hasNext();) {
+ auto *tool = iter.next();
+ SymbolizerScope sym_scope(this);
+ tool->Flush();
+ }
+}
+
+const char *Symbolizer::Demangle(const char *name) {
+ BlockingMutexLock l(&mu_);
+ for (auto iter = Iterator(&tools_); iter.hasNext();) {
+ auto *tool = iter.next();
+ SymbolizerScope sym_scope(this);
+ if (const char *demangled = tool->Demangle(name))
+ return demangled;
+ }
+ return PlatformDemangle(name);
+}
+
+void Symbolizer::PrepareForSandboxing() {
+ BlockingMutexLock l(&mu_);
+ PlatformPrepareForSandboxing();
+}
+
} // namespace __sanitizer
diff --git a/lib/sanitizer_common/sanitizer_symbolizer.h b/lib/sanitizer_common/sanitizer_symbolizer.h
index 3a807744d..225da70de 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer.h
+++ b/lib/sanitizer_common/sanitizer_symbolizer.h
@@ -43,8 +43,7 @@ struct AddressInfo {
AddressInfo();
// Deletes all strings and resets all fields.
void Clear();
- void FillAddressAndModuleInfo(uptr addr, const char *mod_name,
- uptr mod_offset);
+ void FillModuleInfo(const char *mod_name, uptr mod_offset);
};
// Linked list of symbolized frames (each frame is described by AddressInfo).
@@ -74,6 +73,8 @@ struct DataInfo {
void Clear();
};
+class SymbolizerTool;
+
class Symbolizer {
public:
/// Initialize and return platform-specific implementation of symbolizer
@@ -81,26 +82,22 @@ class Symbolizer {
static Symbolizer *GetOrInit();
// Returns a list of symbolized frames for a given address (containing
// all inlined functions, if necessary).
- virtual SymbolizedStack *SymbolizePC(uptr address) {
- return SymbolizedStack::New(address);
- }
- virtual bool SymbolizeData(uptr address, DataInfo *info) {
- return false;
- }
- virtual bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
- uptr *module_address) {
- return false;
- }
- virtual bool CanReturnFileLineInfo() {
- return false;
+ SymbolizedStack *SymbolizePC(uptr address);
+ bool SymbolizeData(uptr address, DataInfo *info);
+ bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
+ uptr *module_address);
+ const char *GetModuleNameForPc(uptr pc) {
+ const char *module_name = 0;
+ uptr unused;
+ if (GetModuleNameAndOffsetForPC(pc, &module_name, &unused))
+ return module_name;
+ return nullptr;
}
// Release internal caches (if any).
- virtual void Flush() {}
+ void Flush();
// Attempts to demangle the provided C++ mangled name.
- virtual const char *Demangle(const char *name) {
- return name;
- }
- virtual void PrepareForSandboxing() {}
+ const char *Demangle(const char *name);
+ void PrepareForSandboxing();
// Allow user to install hooks that would be called before/after Symbolizer
// does the actual file/line info fetching. Specific sanitizers may need this
@@ -115,14 +112,28 @@ class Symbolizer {
private:
/// Platform-specific function for creating a Symbolizer object.
static Symbolizer *PlatformInit();
- /// Initialize the symbolizer in a disabled state. Not thread safe.
- static Symbolizer *Disable();
+
+ virtual bool PlatformFindModuleNameAndOffsetForAddress(
+ uptr address, const char **module_name, uptr *module_offset) {
+ UNIMPLEMENTED();
+ }
+ // Platform-specific default demangler, must not return nullptr.
+ virtual const char *PlatformDemangle(const char *name) { UNIMPLEMENTED(); }
+ virtual void PlatformPrepareForSandboxing() { UNIMPLEMENTED(); }
static Symbolizer *symbolizer_;
static StaticSpinMutex init_mu_;
+ // Mutex locked from public methods of |Symbolizer|, so that the internals
+ // (including individual symbolizer tools and platform-specific methods) are
+ // always synchronized.
+ BlockingMutex mu_;
+
+ typedef IntrusiveList<SymbolizerTool>::Iterator Iterator;
+ IntrusiveList<SymbolizerTool> tools_;
+
protected:
- Symbolizer();
+ explicit Symbolizer(IntrusiveList<SymbolizerTool> tools);
static LowLevelAllocator symbolizer_allocator_;
@@ -137,61 +148,6 @@ class Symbolizer {
};
};
-class ExternalSymbolizerInterface {
- public:
- // Can't declare pure virtual functions in sanitizer runtimes:
- // __cxa_pure_virtual might be unavailable.
- virtual char *SendCommand(bool is_data, const char *module_name,
- uptr module_offset) {
- UNIMPLEMENTED();
- }
-};
-
-// SymbolizerProcess encapsulates communication between the tool and
-// external symbolizer program, running in a different subprocess.
-// SymbolizerProcess may not be used from two threads simultaneously.
-class SymbolizerProcess : public ExternalSymbolizerInterface {
- public:
- explicit SymbolizerProcess(const char *path);
- char *SendCommand(bool is_data, const char *module_name,
- uptr module_offset) override;
-
- private:
- bool Restart();
- char *SendCommandImpl(bool is_data, const char *module_name,
- uptr module_offset);
- bool ReadFromSymbolizer(char *buffer, uptr max_length);
- bool WriteToSymbolizer(const char *buffer, uptr length);
- bool StartSymbolizerSubprocess();
-
- virtual bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
- const char *module_name,
- uptr module_offset) const {
- UNIMPLEMENTED();
- }
-
- virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const {
- UNIMPLEMENTED();
- }
-
- virtual void ExecuteWithDefaultArgs(const char *path_to_binary) const {
- UNIMPLEMENTED();
- }
-
- const char *path_;
- int input_fd_;
- int output_fd_;
-
- static const uptr kBufferSize = 16 * 1024;
- char buffer_[kBufferSize];
-
- static const uptr kMaxTimesRestarted = 5;
- static const int kSymbolizerStartupTimeMillis = 10;
- uptr times_restarted_;
- bool failed_to_start_;
- bool reported_invalid_path_;
-};
-
} // namespace __sanitizer
#endif // SANITIZER_SYMBOLIZER_H
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_internal.h b/lib/sanitizer_common/sanitizer_symbolizer_internal.h
new file mode 100644
index 000000000..66ae809ed
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_symbolizer_internal.h
@@ -0,0 +1,109 @@
+//===-- sanitizer_symbolizer_internal.h -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Header for internal classes and functions to be used by implementations of
+// symbolizers.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SYMBOLIZER_INTERNAL_H
+#define SANITIZER_SYMBOLIZER_INTERNAL_H
+
+#include "sanitizer_symbolizer.h"
+
+namespace __sanitizer {
+
+// Parsing helpers, 'str' is searched for delimiter(s) and a string or uptr
+// is extracted. When extracting a string, a newly allocated (using
+// InternalAlloc) and null-terminataed buffer is returned. They return a pointer
+// to the next characted after the found delimiter.
+const char *ExtractToken(const char *str, const char *delims, char **result);
+const char *ExtractInt(const char *str, const char *delims, int *result);
+const char *ExtractUptr(const char *str, const char *delims, uptr *result);
+const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
+ char **result);
+
+const char *DemangleCXXABI(const char *name);
+
+// SymbolizerTool is an interface that is implemented by individual "tools"
+// that can perform symbolication (external llvm-symbolizer, libbacktrace,
+// Windows DbgHelp symbolizer, etc.).
+class SymbolizerTool {
+ public:
+ // The main |Symbolizer| class implements a "fallback chain" of symbolizer
+ // tools. In a request to symbolize an address, if one tool returns false,
+ // the next tool in the chain will be tried.
+ SymbolizerTool *next;
+
+ SymbolizerTool() : next(nullptr) { }
+
+ // Can't declare pure virtual functions in sanitizer runtimes:
+ // __cxa_pure_virtual might be unavailable.
+
+ // The |stack| parameter is inout. It is pre-filled with the address,
+ // module base and module offset values and is to be used to construct
+ // other stack frames.
+ virtual bool SymbolizePC(uptr addr, SymbolizedStack *stack) {
+ UNIMPLEMENTED();
+ }
+
+ // The |info| parameter is inout. It is pre-filled with the module base
+ // and module offset values.
+ virtual bool SymbolizeData(uptr addr, DataInfo *info) {
+ UNIMPLEMENTED();
+ }
+
+ virtual void Flush() {}
+
+ // Return nullptr to fallback to the default platform-specific demangler.
+ virtual const char *Demangle(const char *name) {
+ return nullptr;
+ }
+};
+
+// SymbolizerProcess encapsulates communication between the tool and
+// external symbolizer program, running in a different subprocess.
+// SymbolizerProcess may not be used from two threads simultaneously.
+class SymbolizerProcess {
+ public:
+ explicit SymbolizerProcess(const char *path, bool use_forkpty = false);
+ const char *SendCommand(const char *command);
+
+ private:
+ bool Restart();
+ const char *SendCommandImpl(const char *command);
+ bool ReadFromSymbolizer(char *buffer, uptr max_length);
+ bool WriteToSymbolizer(const char *buffer, uptr length);
+ bool StartSymbolizerSubprocess();
+
+ virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const {
+ UNIMPLEMENTED();
+ }
+
+ virtual void ExecuteWithDefaultArgs(const char *path_to_binary) const {
+ UNIMPLEMENTED();
+ }
+
+ const char *path_;
+ int input_fd_;
+ int output_fd_;
+
+ static const uptr kBufferSize = 16 * 1024;
+ char buffer_[kBufferSize];
+
+ static const uptr kMaxTimesRestarted = 5;
+ static const int kSymbolizerStartupTimeMillis = 10;
+ uptr times_restarted_;
+ bool failed_to_start_;
+ bool reported_invalid_path_;
+ bool use_forkpty_;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SYMBOLIZER_INTERNAL_H
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
index 9317a78ee..57354668b 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
@@ -33,6 +33,8 @@
namespace __sanitizer {
+static char *DemangleAlloc(const char *name, bool always_alloc);
+
#if SANITIZER_LIBBACKTRACE
namespace {
@@ -86,17 +88,20 @@ char *CplusV3Demangle(const char *name) {
struct SymbolizeCodeCallbackArg {
SymbolizedStack *first;
SymbolizedStack *last;
- const char *module_name;
- uptr module_offset;
-
- void append(SymbolizedStack *f) {
- if (last != nullptr) {
- last->next = f;
- last = f;
- } else {
- first = f;
- last = f;
+ uptr frames_symbolized;
+
+ AddressInfo *get_new_frame(uintptr_t addr) {
+ CHECK(last);
+ if (frames_symbolized > 0) {
+ SymbolizedStack *cur = SymbolizedStack::New(addr);
+ AddressInfo *info = &cur->info;
+ info->FillModuleInfo(first->info.module, first->info.module_offset);
+ last->next = cur;
+ last = cur;
}
+ CHECK_EQ(addr, first->info.address);
+ CHECK_EQ(addr, last->info.address);
+ return &last->info;
}
};
@@ -106,15 +111,12 @@ static int SymbolizeCodePCInfoCallback(void *vdata, uintptr_t addr,
const char *function) {
SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata;
if (function) {
- SymbolizedStack *cur = SymbolizedStack::New(addr);
- cdata->append(cur);
- AddressInfo *info = &cur->info;
- info->FillAddressAndModuleInfo(addr, cdata->module_name,
- cdata->module_offset);
- info->function = LibbacktraceSymbolizer::Demangle(function, true);
+ AddressInfo *info = cdata->get_new_frame(addr);
+ info->function = DemangleAlloc(function, /*always_alloc*/ true);
if (filename)
info->file = internal_strdup(filename);
info->line = lineno;
+ cdata->frames_symbolized++;
}
return 0;
}
@@ -123,12 +125,9 @@ static void SymbolizeCodeCallback(void *vdata, uintptr_t addr,
const char *symname, uintptr_t, uintptr_t) {
SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata;
if (symname) {
- SymbolizedStack *cur = SymbolizedStack::New(addr);
- cdata->append(cur);
- AddressInfo *info = &cur->info;
- info->FillAddressAndModuleInfo(addr, cdata->module_name,
- cdata->module_offset);
- info->function = LibbacktraceSymbolizer::Demangle(symname, true);
+ AddressInfo *info = cdata->get_new_frame(addr);
+ info->function = DemangleAlloc(symname, /*always_alloc*/ true);
+ cdata->frames_symbolized++;
}
}
@@ -136,7 +135,7 @@ static void SymbolizeDataCallback(void *vdata, uintptr_t, const char *symname,
uintptr_t symval, uintptr_t symsize) {
DataInfo *info = (DataInfo *)vdata;
if (symname && symval) {
- info->name = LibbacktraceSymbolizer::Demangle(symname, true);
+ info->name = DemangleAlloc(symname, /*always_alloc*/ true);
info->start = symval;
info->size = symsize;
}
@@ -156,21 +155,18 @@ LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
return new(*alloc) LibbacktraceSymbolizer(state);
}
-SymbolizedStack *LibbacktraceSymbolizer::SymbolizeCode(uptr addr,
- const char *module_name,
- uptr module_offset) {
+bool LibbacktraceSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
SymbolizeCodeCallbackArg data;
- data.first = nullptr;
- data.last = nullptr;
- data.module_name = module_name;
- data.module_offset = module_offset;
+ data.first = stack;
+ data.last = stack;
+ data.frames_symbolized = 0;
backtrace_pcinfo((backtrace_state *)state_, addr, SymbolizeCodePCInfoCallback,
ErrorCallback, &data);
- if (data.first)
- return data.first;
+ if (data.frames_symbolized > 0)
+ return true;
backtrace_syminfo((backtrace_state *)state_, addr, SymbolizeCodeCallback,
ErrorCallback, &data);
- return data.first;
+ return (data.frames_symbolized > 0);
}
bool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
@@ -185,11 +181,9 @@ LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
return 0;
}
-SymbolizedStack *LibbacktraceSymbolizer::SymbolizeCode(uptr addr,
- const char *module_name,
- uptr module_offset) {
+bool LibbacktraceSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
(void)state_;
- return nullptr;
+ return false;
}
bool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
@@ -198,7 +192,7 @@ bool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
#endif // SANITIZER_LIBBACKTRACE
-char *LibbacktraceSymbolizer::Demangle(const char *name, bool always_alloc) {
+static char *DemangleAlloc(const char *name, bool always_alloc) {
#if SANITIZER_LIBBACKTRACE && SANITIZER_CP_DEMANGLE
if (char *demangled = CplusV3Demangle(name))
return demangled;
@@ -208,4 +202,8 @@ char *LibbacktraceSymbolizer::Demangle(const char *name, bool always_alloc) {
return 0;
}
+const char *LibbacktraceSymbolizer::Demangle(const char *name) {
+ return DemangleAlloc(name, /*always_alloc*/ false);
+}
+
} // namespace __sanitizer
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
index 1ff005042..00b465a72 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
+++ b/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
@@ -16,7 +16,7 @@
#include "sanitizer_platform.h"
#include "sanitizer_common.h"
-#include "sanitizer_symbolizer.h"
+#include "sanitizer_symbolizer_internal.h"
#ifndef SANITIZER_LIBBACKTRACE
# define SANITIZER_LIBBACKTRACE 0
@@ -28,17 +28,16 @@
namespace __sanitizer {
-class LibbacktraceSymbolizer {
+class LibbacktraceSymbolizer : public SymbolizerTool {
public:
static LibbacktraceSymbolizer *get(LowLevelAllocator *alloc);
- SymbolizedStack *SymbolizeCode(uptr addr, const char *module_name,
- uptr module_offset);
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
- bool SymbolizeData(uptr addr, DataInfo *info);
+ bool SymbolizeData(uptr addr, DataInfo *info) override;
// May return NULL if demangling failed.
- static char *Demangle(const char *name, bool always_alloc = false);
+ const char *Demangle(const char *name) override;
private:
explicit LibbacktraceSymbolizer(void *state) : state_(state) {}
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc
index 63c9356a5..f1e2289c8 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc
@@ -11,18 +11,62 @@
// run-time libraries.
//===----------------------------------------------------------------------===//
+#include "sanitizer_allocator_internal.h"
#include "sanitizer_internal_defs.h"
-#include "sanitizer_symbolizer.h"
+#include "sanitizer_symbolizer_internal.h"
namespace __sanitizer {
+const char *ExtractToken(const char *str, const char *delims, char **result) {
+ uptr prefix_len = internal_strcspn(str, delims);
+ *result = (char*)InternalAlloc(prefix_len + 1);
+ internal_memcpy(*result, str, prefix_len);
+ (*result)[prefix_len] = '\0';
+ const char *prefix_end = str + prefix_len;
+ if (*prefix_end != '\0') prefix_end++;
+ return prefix_end;
+}
+
+const char *ExtractInt(const char *str, const char *delims, int *result) {
+ char *buff;
+ const char *ret = ExtractToken(str, delims, &buff);
+ if (buff != 0) {
+ *result = (int)internal_atoll(buff);
+ }
+ InternalFree(buff);
+ return ret;
+}
+
+const char *ExtractUptr(const char *str, const char *delims, uptr *result) {
+ char *buff;
+ const char *ret = ExtractToken(str, delims, &buff);
+ if (buff != 0) {
+ *result = (uptr)internal_atoll(buff);
+ }
+ InternalFree(buff);
+ return ret;
+}
+
+const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
+ char **result) {
+ const char *found_delimiter = internal_strstr(str, delimiter);
+ uptr prefix_len =
+ found_delimiter ? found_delimiter - str : internal_strlen(str);
+ *result = (char *)InternalAlloc(prefix_len + 1);
+ internal_memcpy(*result, str, prefix_len);
+ (*result)[prefix_len] = '\0';
+ const char *prefix_end = str + prefix_len;
+ if (*prefix_end != '\0') prefix_end += internal_strlen(delimiter);
+ return prefix_end;
+}
+
Symbolizer *Symbolizer::GetOrInit() {
SpinMutexLock l(&init_mu_);
if (symbolizer_)
return symbolizer_;
- if ((symbolizer_ = PlatformInit()))
- return symbolizer_;
- return Disable();
+ symbolizer_ = PlatformInit();
+ CHECK(symbolizer_);
+ return symbolizer_;
}
} // namespace __sanitizer
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_mac.cc b/lib/sanitizer_common/sanitizer_symbolizer_mac.cc
new file mode 100644
index 000000000..c2397ef98
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_symbolizer_mac.cc
@@ -0,0 +1,151 @@
+//===-- sanitizer_symbolizer_mac.cc ---------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between various sanitizers' runtime libraries.
+//
+// Implementation of Mac-specific "atos" symbolizer.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_MAC
+
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_mac.h"
+#include "sanitizer_symbolizer_mac.h"
+
+namespace __sanitizer {
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <util.h>
+
+bool DlAddrSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
+ Dl_info info;
+ int result = dladdr((const void *)addr, &info);
+ if (!result) return false;
+ const char *demangled = DemangleCXXABI(info.dli_sname);
+ stack->info.function = internal_strdup(demangled);
+ return true;
+}
+
+bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
+ return false;
+}
+
+class AtosSymbolizerProcess : public SymbolizerProcess {
+ public:
+ explicit AtosSymbolizerProcess(const char *path, pid_t parent_pid)
+ : SymbolizerProcess(path, /*use_forkpty*/ true),
+ parent_pid_(parent_pid) {}
+
+ private:
+ bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
+ return (length >= 1 && buffer[length - 1] == '\n');
+ }
+
+ void ExecuteWithDefaultArgs(const char *path_to_binary) const override {
+ // The `atos` binary has some issues with DYLD_ROOT_PATH on i386.
+ unsetenv("DYLD_ROOT_PATH");
+
+ char pid_str[16];
+ internal_snprintf(pid_str, sizeof(pid_str), "%d", parent_pid_);
+ if (GetMacosVersion() == MACOS_VERSION_MAVERICKS) {
+ // On Mavericks atos prints a deprecation warning which we suppress by
+ // passing -d. The warning isn't present on other OSX versions, even the
+ // newer ones.
+ execl(path_to_binary, path_to_binary, "-p", pid_str, "-d", (char *)0);
+ } else {
+ execl(path_to_binary, path_to_binary, "-p", pid_str, (char *)0);
+ }
+ }
+
+ pid_t parent_pid_;
+};
+
+static const char *kAtosErrorMessages[] = {
+ "atos cannot examine process",
+ "unable to get permission to examine process",
+ "An admin user name and password is required",
+ "could not load inserted library",
+ "architecture mismatch between analysis process",
+};
+
+static bool IsAtosErrorMessage(const char *str) {
+ for (uptr i = 0; i < ARRAY_SIZE(kAtosErrorMessages); i++) {
+ if (internal_strstr(str, kAtosErrorMessages[i])) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool ParseCommandOutput(const char *str, SymbolizedStack *res) {
+ // Trim ending newlines.
+ char *trim;
+ ExtractTokenUpToDelimiter(str, "\n", &trim);
+
+ // The line from `atos` is in one of these formats:
+ // myfunction (in library.dylib) (sourcefile.c:17)
+ // myfunction (in library.dylib) + 0x1fe
+ // 0xdeadbeef (in library.dylib) + 0x1fe
+ // 0xdeadbeef (in library.dylib)
+ // 0xdeadbeef
+
+ if (IsAtosErrorMessage(trim)) {
+ Report("atos returned an error: %s\n", trim);
+ InternalFree(trim);
+ return false;
+ }
+
+ const char *rest = trim;
+ char *function_name;
+ rest = ExtractTokenUpToDelimiter(rest, " (in ", &function_name);
+ if (internal_strncmp(function_name, "0x", 2) != 0)
+ res->info.function = function_name;
+ else
+ InternalFree(function_name);
+ rest = ExtractTokenUpToDelimiter(rest, ") ", &res->info.module);
+
+ if (rest[0] == '(') {
+ rest++;
+ rest = ExtractTokenUpToDelimiter(rest, ":", &res->info.file);
+ char *extracted_line_number;
+ rest = ExtractTokenUpToDelimiter(rest, ")", &extracted_line_number);
+ res->info.line = internal_atoll(extracted_line_number);
+ InternalFree(extracted_line_number);
+ }
+
+ InternalFree(trim);
+ return true;
+}
+
+AtosSymbolizer::AtosSymbolizer(const char *path, LowLevelAllocator *allocator)
+ : process_(new(*allocator) AtosSymbolizerProcess(path, getpid())) {}
+
+bool AtosSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
+ if (!process_) return false;
+ char command[32];
+ internal_snprintf(command, sizeof(command), "0x%zx\n", addr);
+ const char *buf = process_->SendCommand(command);
+ if (!buf) return false;
+ if (!ParseCommandOutput(buf, stack)) {
+ process_ = nullptr;
+ return false;
+ }
+ return true;
+}
+
+bool AtosSymbolizer::SymbolizeData(uptr addr, DataInfo *info) { return false; }
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_MAC
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_mac.h b/lib/sanitizer_common/sanitizer_symbolizer_mac.h
new file mode 100644
index 000000000..068644de3
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_symbolizer_mac.h
@@ -0,0 +1,48 @@
+//===-- sanitizer_symbolizer_mac.h ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between various sanitizers' runtime libraries.
+//
+// Header for Mac-specific "atos" symbolizer.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_SYMBOLIZER_MAC_H
+#define SANITIZER_SYMBOLIZER_MAC_H
+
+#include "sanitizer_platform.h"
+#if SANITIZER_MAC
+
+#include "sanitizer_symbolizer_internal.h"
+
+namespace __sanitizer {
+
+class DlAddrSymbolizer : public SymbolizerTool {
+ public:
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
+ bool SymbolizeData(uptr addr, DataInfo *info) override;
+};
+
+class AtosSymbolizerProcess;
+
+class AtosSymbolizer : public SymbolizerTool {
+ public:
+ explicit AtosSymbolizer(const char *path, LowLevelAllocator *allocator);
+
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
+ bool SymbolizeData(uptr addr, DataInfo *info) override;
+
+ private:
+ AtosSymbolizerProcess *process_;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_MAC
+
+#endif // SANITIZER_SYMBOLIZER_MAC_H
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
index deb3429b0..189b0abd8 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
@@ -21,12 +21,10 @@
#include "sanitizer_linux.h"
#include "sanitizer_placement_new.h"
#include "sanitizer_procmaps.h"
-#include "sanitizer_symbolizer.h"
+#include "sanitizer_symbolizer_internal.h"
#include "sanitizer_symbolizer_libbacktrace.h"
+#include "sanitizer_symbolizer_mac.h"
-#include <errno.h>
-#include <stdlib.h>
-#include <sys/wait.h>
#include <unistd.h>
// C++ demangling function, as required by Itanium C++ ABI. This is weak,
@@ -41,7 +39,7 @@ namespace __cxxabiv1 {
namespace __sanitizer {
// Attempts to demangle the name via __cxa_demangle from __cxxabiv1.
-static const char *DemangleCXXABI(const char *name) {
+const char *DemangleCXXABI(const char *name) {
// FIXME: __cxa_demangle aggressively insists on allocating memory.
// There's not much we can do about that, short of providing our
// own demangler (libc++abi's implementation could be adapted so that
@@ -55,217 +53,6 @@ static const char *DemangleCXXABI(const char *name) {
return name;
}
-// Extracts the prefix of "str" that consists of any characters not
-// present in "delims" string, and copies this prefix to "result", allocating
-// space for it.
-// Returns a pointer to "str" after skipping extracted prefix and first
-// delimiter char.
-static const char *ExtractToken(const char *str, const char *delims,
- char **result) {
- uptr prefix_len = internal_strcspn(str, delims);
- *result = (char*)InternalAlloc(prefix_len + 1);
- internal_memcpy(*result, str, prefix_len);
- (*result)[prefix_len] = '\0';
- const char *prefix_end = str + prefix_len;
- if (*prefix_end != '\0') prefix_end++;
- return prefix_end;
-}
-
-// Same as ExtractToken, but converts extracted token to integer.
-static const char *ExtractInt(const char *str, const char *delims,
- int *result) {
- char *buff;
- const char *ret = ExtractToken(str, delims, &buff);
- if (buff != 0) {
- *result = (int)internal_atoll(buff);
- }
- InternalFree(buff);
- return ret;
-}
-
-static const char *ExtractUptr(const char *str, const char *delims,
- uptr *result) {
- char *buff;
- const char *ret = ExtractToken(str, delims, &buff);
- if (buff != 0) {
- *result = (uptr)internal_atoll(buff);
- }
- InternalFree(buff);
- return ret;
-}
-
-SymbolizerProcess::SymbolizerProcess(const char *path)
- : path_(path),
- input_fd_(kInvalidFd),
- output_fd_(kInvalidFd),
- times_restarted_(0),
- failed_to_start_(false),
- reported_invalid_path_(false) {
- CHECK(path_);
- CHECK_NE(path_[0], '\0');
-}
-
-char *SymbolizerProcess::SendCommand(bool is_data, const char *module_name,
- uptr module_offset) {
- for (; times_restarted_ < kMaxTimesRestarted; times_restarted_++) {
- // Start or restart symbolizer if we failed to send command to it.
- if (char *res = SendCommandImpl(is_data, module_name, module_offset))
- return res;
- Restart();
- }
- if (!failed_to_start_) {
- Report("WARNING: Failed to use and restart external symbolizer!\n");
- failed_to_start_ = true;
- }
- return 0;
-}
-
-bool SymbolizerProcess::Restart() {
- if (input_fd_ != kInvalidFd)
- internal_close(input_fd_);
- if (output_fd_ != kInvalidFd)
- internal_close(output_fd_);
- return StartSymbolizerSubprocess();
-}
-
-char *SymbolizerProcess::SendCommandImpl(bool is_data, const char *module_name,
- uptr module_offset) {
- if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd)
- return 0;
- CHECK(module_name);
- if (!RenderInputCommand(buffer_, kBufferSize, is_data, module_name,
- module_offset))
- return 0;
- if (!WriteToSymbolizer(buffer_, internal_strlen(buffer_)))
- return 0;
- if (!ReadFromSymbolizer(buffer_, kBufferSize))
- return 0;
- return buffer_;
-}
-
-bool SymbolizerProcess::ReadFromSymbolizer(char *buffer, uptr max_length) {
- if (max_length == 0)
- return true;
- uptr read_len = 0;
- while (true) {
- uptr just_read = internal_read(input_fd_, buffer + read_len,
- max_length - read_len - 1);
- // We can't read 0 bytes, as we don't expect external symbolizer to close
- // its stdout.
- if (just_read == 0 || just_read == (uptr)-1) {
- Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);
- return false;
- }
- read_len += just_read;
- if (ReachedEndOfOutput(buffer, read_len))
- break;
- }
- buffer[read_len] = '\0';
- return true;
-}
-
-bool SymbolizerProcess::WriteToSymbolizer(const char *buffer, uptr length) {
- if (length == 0)
- return true;
- uptr write_len = internal_write(output_fd_, buffer, length);
- if (write_len == 0 || write_len == (uptr)-1) {
- Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_);
- return false;
- }
- return true;
-}
-
-bool SymbolizerProcess::StartSymbolizerSubprocess() {
- if (!FileExists(path_)) {
- if (!reported_invalid_path_) {
- Report("WARNING: invalid path to external symbolizer!\n");
- reported_invalid_path_ = true;
- }
- return false;
- }
-
- int *infd = NULL;
- int *outfd = NULL;
- // The client program may close its stdin and/or stdout and/or stderr
- // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
- // In this case the communication between the forked processes may be
- // broken if either the parent or the child tries to close or duplicate
- // these descriptors. The loop below produces two pairs of file
- // descriptors, each greater than 2 (stderr).
- int sock_pair[5][2];
- for (int i = 0; i < 5; i++) {
- if (pipe(sock_pair[i]) == -1) {
- for (int j = 0; j < i; j++) {
- internal_close(sock_pair[j][0]);
- internal_close(sock_pair[j][1]);
- }
- Report("WARNING: Can't create a socket pair to start "
- "external symbolizer (errno: %d)\n", errno);
- return false;
- } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {
- if (infd == NULL) {
- infd = sock_pair[i];
- } else {
- outfd = sock_pair[i];
- for (int j = 0; j < i; j++) {
- if (sock_pair[j] == infd) continue;
- internal_close(sock_pair[j][0]);
- internal_close(sock_pair[j][1]);
- }
- break;
- }
- }
- }
- CHECK(infd);
- CHECK(outfd);
-
- // Real fork() may call user callbacks registered with pthread_atfork().
- int pid = internal_fork();
- if (pid == -1) {
- // Fork() failed.
- internal_close(infd[0]);
- internal_close(infd[1]);
- internal_close(outfd[0]);
- internal_close(outfd[1]);
- Report("WARNING: failed to fork external symbolizer "
- " (errno: %d)\n", errno);
- return false;
- } else if (pid == 0) {
- // Child subprocess.
- internal_close(STDOUT_FILENO);
- internal_close(STDIN_FILENO);
- internal_dup2(outfd[0], STDIN_FILENO);
- internal_dup2(infd[1], STDOUT_FILENO);
- internal_close(outfd[0]);
- internal_close(outfd[1]);
- internal_close(infd[0]);
- internal_close(infd[1]);
- for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--)
- internal_close(fd);
- ExecuteWithDefaultArgs(path_);
- internal__exit(1);
- }
-
- // Continue execution in parent process.
- internal_close(outfd[0]);
- internal_close(infd[1]);
- input_fd_ = infd[0];
- output_fd_ = outfd[1];
-
- // Check that symbolizer subprocess started successfully.
- int pid_status;
- SleepForMillis(kSymbolizerStartupTimeMillis);
- int exited_pid = waitpid(pid, &pid_status, WNOHANG);
- if (exited_pid != 0) {
- // Either waitpid failed, or child has already exited.
- Report("WARNING: external symbolizer didn't start up correctly!\n");
- return false;
- }
-
- return true;
-}
-
-
// Parses one or more two-line strings in the following format:
// <function_name>
// <file_name>:<line_number>[:<column_number>]
@@ -288,8 +75,7 @@ static void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res) {
top_frame = false;
} else {
cur = SymbolizedStack::New(res->info.address);
- cur->info.FillAddressAndModuleInfo(res->info.address, res->info.module,
- res->info.module_offset);
+ cur->info.FillModuleInfo(res->info.module, res->info.module_offset);
last->next = cur;
last = cur;
}
@@ -343,13 +129,6 @@ class LLVMSymbolizerProcess : public SymbolizerProcess {
explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {}
private:
- bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
- const char *module_name, uptr module_offset) const {
- internal_snprintf(buffer, max_length, "%s\"%s\" 0x%zx\n",
- is_data ? "DATA " : "", module_name, module_offset);
- return true;
- }
-
bool ReachedEndOfOutput(const char *buffer, uptr length) const {
// Empty line marks the end of llvm-symbolizer output.
return length >= 2 && buffer[length - 1] == '\n' &&
@@ -377,6 +156,44 @@ class LLVMSymbolizerProcess : public SymbolizerProcess {
}
};
+class LLVMSymbolizer : public SymbolizerTool {
+ public:
+ explicit LLVMSymbolizer(const char *path, LowLevelAllocator *allocator)
+ : symbolizer_process_(new(*allocator) LLVMSymbolizerProcess(path)) {}
+
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
+ if (const char *buf = SendCommand(/*is_data*/ false, stack->info.module,
+ stack->info.module_offset)) {
+ ParseSymbolizePCOutput(buf, stack);
+ return true;
+ }
+ return false;
+ }
+
+ bool SymbolizeData(uptr addr, DataInfo *info) override {
+ if (const char *buf =
+ SendCommand(/*is_data*/ true, info->module, info->module_offset)) {
+ ParseSymbolizeDataOutput(buf, info);
+ info->start += (addr - info->module_offset); // Add the base address.
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ const char *SendCommand(bool is_data, const char *module_name,
+ uptr module_offset) {
+ CHECK(module_name);
+ internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n",
+ is_data ? "DATA " : "", module_name, module_offset);
+ return symbolizer_process_->SendCommand(buffer_);
+ }
+
+ LLVMSymbolizerProcess *symbolizer_process_;
+ static const uptr kBufferSize = 16 * 1024;
+ char buffer_[kBufferSize];
+};
+
class Addr2LineProcess : public SymbolizerProcess {
public:
Addr2LineProcess(const char *path, const char *module_name)
@@ -385,15 +202,6 @@ class Addr2LineProcess : public SymbolizerProcess {
const char *module_name() const { return module_name_; }
private:
- bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
- const char *module_name, uptr module_offset) const {
- if (is_data)
- return false;
- CHECK_EQ(0, internal_strcmp(module_name, module_name_));
- internal_snprintf(buffer, max_length, "0x%zx\n", module_offset);
- return true;
- }
-
bool ReachedEndOfOutput(const char *buffer, uptr length) const {
// Output should consist of two lines.
int num_lines = 0;
@@ -413,16 +221,28 @@ class Addr2LineProcess : public SymbolizerProcess {
const char *module_name_; // Owned, leaked.
};
-class Addr2LinePool : public ExternalSymbolizerInterface {
+class Addr2LinePool : public SymbolizerTool {
public:
explicit Addr2LinePool(const char *addr2line_path,
LowLevelAllocator *allocator)
: addr2line_path_(addr2line_path), allocator_(allocator),
addr2line_pool_(16) {}
- char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
- if (is_data)
- return 0;
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
+ if (const char *buf =
+ SendCommand(stack->info.module, stack->info.module_offset)) {
+ ParseSymbolizePCOutput(buf, stack);
+ return true;
+ }
+ return false;
+ }
+
+ bool SymbolizeData(uptr addr, DataInfo *info) override {
+ return false;
+ }
+
+ private:
+ const char *SendCommand(const char *module_name, uptr module_offset) {
Addr2LineProcess *addr2line = 0;
for (uptr i = 0; i < addr2line_pool_.size(); ++i) {
if (0 ==
@@ -436,10 +256,13 @@ class Addr2LinePool : public ExternalSymbolizerInterface {
new(*allocator_) Addr2LineProcess(addr2line_path_, module_name);
addr2line_pool_.push_back(addr2line);
}
- return addr2line->SendCommand(is_data, module_name, module_offset);
+ CHECK_EQ(0, internal_strcmp(module_name, addr2line->module_name()));
+ char buffer_[kBufferSize];
+ internal_snprintf(buffer_, kBufferSize, "0x%zx\n", module_offset);
+ return addr2line->SendCommand(buffer_);
}
- private:
+ static const uptr kBufferSize = 32;
const char *addr2line_path_;
LowLevelAllocator *allocator_;
InternalMmapVector<Addr2LineProcess*> addr2line_pool_;
@@ -460,10 +283,8 @@ int __sanitizer_symbolize_demangle(const char *Name, char *Buffer,
int MaxLength);
} // extern "C"
-class InternalSymbolizer {
+class InternalSymbolizer : public SymbolizerTool {
public:
- typedef bool (*SanitizerSymbolizeFn)(const char*, u64, char*, int);
-
static InternalSymbolizer *get(LowLevelAllocator *alloc) {
if (__sanitizer_symbolize_code != 0 &&
__sanitizer_symbolize_data != 0) {
@@ -472,20 +293,29 @@ class InternalSymbolizer {
return 0;
}
- char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
- SanitizerSymbolizeFn symbolize_fn = is_data ? __sanitizer_symbolize_data
- : __sanitizer_symbolize_code;
- if (symbolize_fn(module_name, module_offset, buffer_, kBufferSize))
- return buffer_;
- return 0;
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
+ bool result = __sanitizer_symbolize_code(
+ stack->info.module, stack->info.module_offset, buffer_, kBufferSize);
+ if (result) ParseSymbolizePCOutput(buffer_, stack);
+ return result;
+ }
+
+ bool SymbolizeData(uptr addr, DataInfo *info) override {
+ bool result = __sanitizer_symbolize_data(info->module, info->module_offset,
+ buffer_, kBufferSize);
+ if (result) {
+ ParseSymbolizeDataOutput(buffer_, info);
+ info->start += (addr - info->module_offset); // Add the base address.
+ }
+ return result;
}
- void Flush() {
+ void Flush() override {
if (__sanitizer_symbolize_flush)
__sanitizer_symbolize_flush();
}
- const char *Demangle(const char *name) {
+ const char *Demangle(const char *name) override {
if (__sanitizer_symbolize_demangle) {
for (uptr res_length = 1024;
res_length <= InternalSizeClassMap::kMaxSize;) {
@@ -512,146 +342,35 @@ class InternalSymbolizer {
};
#else // SANITIZER_SUPPORTS_WEAK_HOOKS
-class InternalSymbolizer {
+class InternalSymbolizer : public SymbolizerTool {
public:
static InternalSymbolizer *get(LowLevelAllocator *alloc) { return 0; }
- char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
- return 0;
- }
- void Flush() { }
- const char *Demangle(const char *name) { return name; }
};
#endif // SANITIZER_SUPPORTS_WEAK_HOOKS
class POSIXSymbolizer : public Symbolizer {
public:
- POSIXSymbolizer(ExternalSymbolizerInterface *external_symbolizer,
- InternalSymbolizer *internal_symbolizer,
- LibbacktraceSymbolizer *libbacktrace_symbolizer)
- : Symbolizer(),
- external_symbolizer_(external_symbolizer),
- internal_symbolizer_(internal_symbolizer),
- libbacktrace_symbolizer_(libbacktrace_symbolizer) {}
-
- SymbolizedStack *SymbolizePC(uptr addr) override {
- BlockingMutexLock l(&mu_);
- const char *module_name;
- uptr module_offset;
- if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset))
- return SymbolizedStack::New(addr);
- // First, try to use libbacktrace symbolizer (if it's available).
- if (libbacktrace_symbolizer_ != 0) {
- mu_.CheckLocked();
- if (SymbolizedStack *res = libbacktrace_symbolizer_->SymbolizeCode(
- addr, module_name, module_offset))
- return res;
- }
- // Always fill data about module name and offset.
- SymbolizedStack *res = SymbolizedStack::New(addr);
- res->info.FillAddressAndModuleInfo(addr, module_name, module_offset);
-
- const char *str = SendCommand(false, module_name, module_offset);
- if (str == 0) {
- // Symbolizer was not initialized or failed.
- return res;
- }
-
- ParseSymbolizePCOutput(str, res);
- return res;
- }
-
- bool SymbolizeData(uptr addr, DataInfo *info) override {
- BlockingMutexLock l(&mu_);
- LoadedModule *module = FindModuleForAddress(addr);
- if (module == 0)
- return false;
- const char *module_name = module->full_name();
- uptr module_offset = addr - module->base_address();
- info->Clear();
- info->module = internal_strdup(module_name);
- info->module_offset = module_offset;
- // First, try to use libbacktrace symbolizer (if it's available).
- if (libbacktrace_symbolizer_ != 0) {
- mu_.CheckLocked();
- if (libbacktrace_symbolizer_->SymbolizeData(addr, info))
- return true;
- }
- const char *str = SendCommand(true, module_name, module_offset);
- if (str == 0)
- return true;
- ParseSymbolizeDataOutput(str, info);
- info->start += module->base_address();
- return true;
- }
-
- bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
- uptr *module_address) override {
- BlockingMutexLock l(&mu_);
- return FindModuleNameAndOffsetForAddress(pc, module_name, module_address);
- }
-
- bool CanReturnFileLineInfo() override {
- return internal_symbolizer_ != 0 || external_symbolizer_ != 0 ||
- libbacktrace_symbolizer_ != 0;
- }
-
- void Flush() override {
- BlockingMutexLock l(&mu_);
- if (internal_symbolizer_ != 0) {
- SymbolizerScope sym_scope(this);
- internal_symbolizer_->Flush();
- }
- }
+ explicit POSIXSymbolizer(IntrusiveList<SymbolizerTool> tools)
+ : Symbolizer(tools), n_modules_(0), modules_fresh_(false) {}
- const char *Demangle(const char *name) override {
- BlockingMutexLock l(&mu_);
- // Run hooks even if we don't use internal symbolizer, as cxxabi
- // demangle may call system functions.
- SymbolizerScope sym_scope(this);
- // Try to use libbacktrace demangler (if available).
- if (libbacktrace_symbolizer_ != 0) {
- if (const char *demangled = libbacktrace_symbolizer_->Demangle(name))
- return demangled;
- }
- if (internal_symbolizer_ != 0)
- return internal_symbolizer_->Demangle(name);
+ private:
+ const char *PlatformDemangle(const char *name) override {
return DemangleCXXABI(name);
}
- void PrepareForSandboxing() override {
+ void PlatformPrepareForSandboxing() override {
#if SANITIZER_LINUX && !SANITIZER_ANDROID
- BlockingMutexLock l(&mu_);
// Cache /proc/self/exe on Linux.
CacheBinaryName();
#endif
}
- private:
- char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
- mu_.CheckLocked();
- // First, try to use internal symbolizer.
- if (internal_symbolizer_) {
- SymbolizerScope sym_scope(this);
- return internal_symbolizer_->SendCommand(is_data, module_name,
- module_offset);
- }
- // Otherwise, fall back to external symbolizer.
- if (external_symbolizer_) {
- SymbolizerScope sym_scope(this);
- return external_symbolizer_->SendCommand(is_data, module_name,
- module_offset);
- }
- return 0;
- }
-
LoadedModule *FindModuleForAddress(uptr address) {
- mu_.CheckLocked();
bool modules_were_reloaded = false;
- if (modules_ == 0 || !modules_fresh_) {
- modules_ = (LoadedModule*)(symbolizer_allocator_.Allocate(
- kMaxNumberOfModuleContexts * sizeof(LoadedModule)));
- CHECK(modules_);
+ if (!modules_fresh_) {
+ for (uptr i = 0; i < n_modules_; i++)
+ modules_[i].clear();
n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts,
/* filter */ 0);
CHECK_GT(n_modules_, 0);
@@ -675,9 +394,9 @@ class POSIXSymbolizer : public Symbolizer {
return 0;
}
- bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name,
- uptr *module_offset) {
- mu_.CheckLocked();
+ bool PlatformFindModuleNameAndOffsetForAddress(uptr address,
+ const char **module_name,
+ uptr *module_offset) override {
LoadedModule *module = FindModuleForAddress(address);
if (module == 0)
return false;
@@ -688,53 +407,94 @@ class POSIXSymbolizer : public Symbolizer {
// 16K loaded modules should be enough for everyone.
static const uptr kMaxNumberOfModuleContexts = 1 << 14;
- LoadedModule *modules_; // Array of module descriptions is leaked.
+ LoadedModule modules_[kMaxNumberOfModuleContexts];
uptr n_modules_;
// If stale, need to reload the modules before looking up addresses.
bool modules_fresh_;
- BlockingMutex mu_;
-
- ExternalSymbolizerInterface *external_symbolizer_; // Leaked.
- InternalSymbolizer *const internal_symbolizer_; // Leaked.
- LibbacktraceSymbolizer *libbacktrace_symbolizer_; // Leaked.
};
-Symbolizer *Symbolizer::PlatformInit() {
+static SymbolizerTool *ChooseExternalSymbolizer(LowLevelAllocator *allocator) {
+ const char *path = common_flags()->external_symbolizer_path;
+ const char *binary_name = path ? StripModuleName(path) : "";
+ if (path && path[0] == '\0') {
+ VReport(2, "External symbolizer is explicitly disabled.\n");
+ return nullptr;
+ } else if (!internal_strcmp(binary_name, "llvm-symbolizer")) {
+ VReport(2, "Using llvm-symbolizer at user-specified path: %s\n", path);
+ return new(*allocator) LLVMSymbolizer(path, allocator);
+ } else if (!internal_strcmp(binary_name, "atos")) {
+#if SANITIZER_MAC
+ VReport(2, "Using atos at user-specified path: %s\n", path);
+ return new(*allocator) AtosSymbolizer(path, allocator);
+#else // SANITIZER_MAC
+ Report("ERROR: Using `atos` is only supported on Darwin.\n");
+ Die();
+#endif // SANITIZER_MAC
+ } else if (!internal_strcmp(binary_name, "addr2line")) {
+ VReport(2, "Using addr2line at user-specified path: %s\n", path);
+ return new(*allocator) Addr2LinePool(path, allocator);
+ } else if (path) {
+ Report("ERROR: External symbolizer path is set to '%s' which isn't "
+ "a known symbolizer. Please set the path to the llvm-symbolizer "
+ "binary or other known tool.\n", path);
+ Die();
+ }
+
+ // Otherwise symbolizer program is unknown, let's search $PATH
+ CHECK(path == nullptr);
+ if (const char *found_path = FindPathToBinary("llvm-symbolizer")) {
+ VReport(2, "Using llvm-symbolizer found at: %s\n", found_path);
+ return new(*allocator) LLVMSymbolizer(found_path, allocator);
+ }
+#if SANITIZER_MAC
+ if (const char *found_path = FindPathToBinary("atos")) {
+ VReport(2, "Using atos found at: %s\n", found_path);
+ return new(*allocator) AtosSymbolizer(found_path, allocator);
+ }
+#endif // SANITIZER_MAC
+ if (common_flags()->allow_addr2line) {
+ if (const char *found_path = FindPathToBinary("addr2line")) {
+ VReport(2, "Using addr2line found at: %s\n", found_path);
+ return new(*allocator) Addr2LinePool(found_path, allocator);
+ }
+ }
+ return nullptr;
+}
+
+static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
+ LowLevelAllocator *allocator) {
if (!common_flags()->symbolize) {
- return new(symbolizer_allocator_) POSIXSymbolizer(0, 0, 0);
+ VReport(2, "Symbolizer is disabled.\n");
+ return;
}
- InternalSymbolizer* internal_symbolizer =
- InternalSymbolizer::get(&symbolizer_allocator_);
- ExternalSymbolizerInterface *external_symbolizer = 0;
- LibbacktraceSymbolizer *libbacktrace_symbolizer = 0;
-
- if (!internal_symbolizer) {
- libbacktrace_symbolizer =
- LibbacktraceSymbolizer::get(&symbolizer_allocator_);
- if (!libbacktrace_symbolizer) {
- const char *path_to_external = common_flags()->external_symbolizer_path;
- if (path_to_external && path_to_external[0] == '\0') {
- // External symbolizer is explicitly disabled. Do nothing.
- } else {
- // Find path to llvm-symbolizer if it's not provided.
- if (!path_to_external)
- path_to_external = FindPathToBinary("llvm-symbolizer");
- if (path_to_external) {
- external_symbolizer = new(symbolizer_allocator_)
- LLVMSymbolizerProcess(path_to_external);
- } else if (common_flags()->allow_addr2line) {
- // If llvm-symbolizer is not found, try to use addr2line.
- if (const char *addr2line_path = FindPathToBinary("addr2line")) {
- external_symbolizer = new(symbolizer_allocator_)
- Addr2LinePool(addr2line_path, &symbolizer_allocator_);
- }
- }
- }
- }
+ if (SymbolizerTool *tool = InternalSymbolizer::get(allocator)) {
+ VReport(2, "Using internal symbolizer.\n");
+ list->push_back(tool);
+ return;
+ }
+ if (SymbolizerTool *tool = LibbacktraceSymbolizer::get(allocator)) {
+ VReport(2, "Using libbacktrace symbolizer.\n");
+ list->push_back(tool);
+ return;
}
- return new(symbolizer_allocator_) POSIXSymbolizer(
- external_symbolizer, internal_symbolizer, libbacktrace_symbolizer);
+ if (SymbolizerTool *tool = ChooseExternalSymbolizer(allocator)) {
+ list->push_back(tool);
+ } else {
+ VReport(2, "No internal or external symbolizer found.\n");
+ }
+
+#if SANITIZER_MAC
+ VReport(2, "Using dladdr symbolizer.\n");
+ list->push_back(new(*allocator) DlAddrSymbolizer());
+#endif // SANITIZER_MAC
+}
+
+Symbolizer *Symbolizer::PlatformInit() {
+ IntrusiveList<SymbolizerTool> list;
+ list.clear();
+ ChooseSymbolizerTools(&list, &symbolizer_allocator_);
+ return new(symbolizer_allocator_) POSIXSymbolizer(list);
}
} // namespace __sanitizer
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc
new file mode 100644
index 000000000..98d16e04e
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc
@@ -0,0 +1,228 @@
+//===-- sanitizer_symbolizer_process_libcdep.cc ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of SymbolizerProcess used by external symbolizers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_POSIX
+#include "sanitizer_symbolizer_internal.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#if SANITIZER_MAC
+#include <util.h> // for forkpty()
+#endif // SANITIZER_MAC
+
+namespace __sanitizer {
+
+SymbolizerProcess::SymbolizerProcess(const char *path, bool use_forkpty)
+ : path_(path),
+ input_fd_(kInvalidFd),
+ output_fd_(kInvalidFd),
+ times_restarted_(0),
+ failed_to_start_(false),
+ reported_invalid_path_(false),
+ use_forkpty_(use_forkpty) {
+ CHECK(path_);
+ CHECK_NE(path_[0], '\0');
+}
+
+const char *SymbolizerProcess::SendCommand(const char *command) {
+ for (; times_restarted_ < kMaxTimesRestarted; times_restarted_++) {
+ // Start or restart symbolizer if we failed to send command to it.
+ if (const char *res = SendCommandImpl(command))
+ return res;
+ Restart();
+ }
+ if (!failed_to_start_) {
+ Report("WARNING: Failed to use and restart external symbolizer!\n");
+ failed_to_start_ = true;
+ }
+ return 0;
+}
+
+bool SymbolizerProcess::Restart() {
+ if (input_fd_ != kInvalidFd)
+ internal_close(input_fd_);
+ if (output_fd_ != kInvalidFd)
+ internal_close(output_fd_);
+ return StartSymbolizerSubprocess();
+}
+
+const char *SymbolizerProcess::SendCommandImpl(const char *command) {
+ if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd)
+ return 0;
+ if (!WriteToSymbolizer(command, internal_strlen(command)))
+ return 0;
+ if (!ReadFromSymbolizer(buffer_, kBufferSize))
+ return 0;
+ return buffer_;
+}
+
+bool SymbolizerProcess::ReadFromSymbolizer(char *buffer, uptr max_length) {
+ if (max_length == 0)
+ return true;
+ uptr read_len = 0;
+ while (true) {
+ uptr just_read = internal_read(input_fd_, buffer + read_len,
+ max_length - read_len - 1);
+ // We can't read 0 bytes, as we don't expect external symbolizer to close
+ // its stdout.
+ if (just_read == 0 || just_read == (uptr)-1) {
+ Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);
+ return false;
+ }
+ read_len += just_read;
+ if (ReachedEndOfOutput(buffer, read_len))
+ break;
+ }
+ buffer[read_len] = '\0';
+ return true;
+}
+
+bool SymbolizerProcess::WriteToSymbolizer(const char *buffer, uptr length) {
+ if (length == 0)
+ return true;
+ uptr write_len = internal_write(output_fd_, buffer, length);
+ if (write_len == 0 || write_len == (uptr)-1) {
+ Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_);
+ return false;
+ }
+ return true;
+}
+
+bool SymbolizerProcess::StartSymbolizerSubprocess() {
+ if (!FileExists(path_)) {
+ if (!reported_invalid_path_) {
+ Report("WARNING: invalid path to external symbolizer!\n");
+ reported_invalid_path_ = true;
+ }
+ return false;
+ }
+
+ int pid;
+ if (use_forkpty_) {
+#if SANITIZER_MAC
+ fd_t fd = kInvalidFd;
+ // Use forkpty to disable buffering in the new terminal.
+ pid = forkpty(&fd, 0, 0, 0);
+ if (pid == -1) {
+ // forkpty() failed.
+ Report("WARNING: failed to fork external symbolizer (errno: %d)\n",
+ errno);
+ return false;
+ } else if (pid == 0) {
+ // Child subprocess.
+ ExecuteWithDefaultArgs(path_);
+ internal__exit(1);
+ }
+
+ // Continue execution in parent process.
+ input_fd_ = output_fd_ = fd;
+
+ // Disable echo in the new terminal, disable CR.
+ struct termios termflags;
+ tcgetattr(fd, &termflags);
+ termflags.c_oflag &= ~ONLCR;
+ termflags.c_lflag &= ~ECHO;
+ tcsetattr(fd, TCSANOW, &termflags);
+#else // SANITIZER_MAC
+ UNIMPLEMENTED();
+#endif // SANITIZER_MAC
+ } else {
+ int *infd = NULL;
+ int *outfd = NULL;
+ // The client program may close its stdin and/or stdout and/or stderr
+ // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
+ // In this case the communication between the forked processes may be
+ // broken if either the parent or the child tries to close or duplicate
+ // these descriptors. The loop below produces two pairs of file
+ // descriptors, each greater than 2 (stderr).
+ int sock_pair[5][2];
+ for (int i = 0; i < 5; i++) {
+ if (pipe(sock_pair[i]) == -1) {
+ for (int j = 0; j < i; j++) {
+ internal_close(sock_pair[j][0]);
+ internal_close(sock_pair[j][1]);
+ }
+ Report("WARNING: Can't create a socket pair to start "
+ "external symbolizer (errno: %d)\n", errno);
+ return false;
+ } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {
+ if (infd == NULL) {
+ infd = sock_pair[i];
+ } else {
+ outfd = sock_pair[i];
+ for (int j = 0; j < i; j++) {
+ if (sock_pair[j] == infd) continue;
+ internal_close(sock_pair[j][0]);
+ internal_close(sock_pair[j][1]);
+ }
+ break;
+ }
+ }
+ }
+ CHECK(infd);
+ CHECK(outfd);
+
+ // Real fork() may call user callbacks registered with pthread_atfork().
+ pid = internal_fork();
+ if (pid == -1) {
+ // Fork() failed.
+ internal_close(infd[0]);
+ internal_close(infd[1]);
+ internal_close(outfd[0]);
+ internal_close(outfd[1]);
+ Report("WARNING: failed to fork external symbolizer "
+ " (errno: %d)\n", errno);
+ return false;
+ } else if (pid == 0) {
+ // Child subprocess.
+ internal_close(STDOUT_FILENO);
+ internal_close(STDIN_FILENO);
+ internal_dup2(outfd[0], STDIN_FILENO);
+ internal_dup2(infd[1], STDOUT_FILENO);
+ internal_close(outfd[0]);
+ internal_close(outfd[1]);
+ internal_close(infd[0]);
+ internal_close(infd[1]);
+ for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--)
+ internal_close(fd);
+ ExecuteWithDefaultArgs(path_);
+ internal__exit(1);
+ }
+
+ // Continue execution in parent process.
+ internal_close(outfd[0]);
+ internal_close(infd[1]);
+ input_fd_ = infd[0];
+ output_fd_ = outfd[1];
+ }
+
+ // Check that symbolizer subprocess started successfully.
+ int pid_status;
+ SleepForMillis(kSymbolizerStartupTimeMillis);
+ int exited_pid = waitpid(pid, &pid_status, WNOHANG);
+ if (exited_pid != 0) {
+ // Either waitpid failed, or child has already exited.
+ Report("WARNING: external symbolizer didn't start up correctly!\n");
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_POSIX
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_win.cc b/lib/sanitizer_common/sanitizer_symbolizer_win.cc
index ed96a3a89..67ed4b325 100644
--- a/lib/sanitizer_common/sanitizer_symbolizer_win.cc
+++ b/lib/sanitizer_common/sanitizer_symbolizer_win.cc
@@ -18,139 +18,153 @@
#include <dbghelp.h>
#pragma comment(lib, "dbghelp.lib")
-#include "sanitizer_symbolizer.h"
+#include "sanitizer_symbolizer_win.h"
+#include "sanitizer_symbolizer_internal.h"
namespace __sanitizer {
-class WinSymbolizer : public Symbolizer {
- public:
- WinSymbolizer() : initialized_(false) {}
-
- SymbolizedStack *SymbolizePC(uptr addr) override {
- SymbolizedStack *frame = SymbolizedStack::New(addr);
-
- BlockingMutexLock l(&dbghelp_mu_);
- InitializeIfNeeded();
-
- // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
- char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
- PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
- symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
- symbol->MaxNameLen = MAX_SYM_NAME;
- DWORD64 offset = 0;
- BOOL got_objname = SymFromAddr(GetCurrentProcess(),
- (DWORD64)addr, &offset, symbol);
- if (!got_objname)
- return frame;
-
- DWORD unused;
- IMAGEHLP_LINE64 line_info;
- line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
- BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr,
- &unused, &line_info);
- frame->info.function = internal_strdup(symbol->Name);
- frame->info.function_offset = (uptr)offset;
- if (got_fileline) {
- frame->info.file = internal_strdup(line_info.FileName);
- frame->info.line = line_info.LineNumber;
- }
-
- IMAGEHLP_MODULE64 mod_info;
- internal_memset(&mod_info, 0, sizeof(mod_info));
- mod_info.SizeOfStruct = sizeof(mod_info);
- if (SymGetModuleInfo64(GetCurrentProcess(), addr, &mod_info))
- frame->info.FillAddressAndModuleInfo(addr, mod_info.ImageName,
- addr - (uptr)mod_info.BaseOfImage);
- return frame;
- }
+namespace {
- bool CanReturnFileLineInfo() override {
- return true;
+bool is_dbghelp_initialized = false;
+
+bool TrySymInitialize() {
+ SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
+ return SymInitialize(GetCurrentProcess(), 0, TRUE);
+ // FIXME: We don't call SymCleanup() on exit yet - should we?
+}
+
+// Initializes DbgHelp library, if it's not yet initialized. Calls to this
+// function should be synchronized with respect to other calls to DbgHelp API
+// (e.g. from WinSymbolizerTool).
+void InitializeDbgHelpIfNeeded() {
+ if (is_dbghelp_initialized)
+ return;
+ if (!TrySymInitialize()) {
+ // OK, maybe the client app has called SymInitialize already.
+ // That's a bit unfortunate for us as all the DbgHelp functions are
+ // single-threaded and we can't coordinate with the app.
+ // FIXME: Can we stop the other threads at this point?
+ // Anyways, we have to reconfigure stuff to make sure that SymInitialize
+ // has all the appropriate options set.
+ // Cross our fingers and reinitialize DbgHelp.
+ Report("*** WARNING: Failed to initialize DbgHelp! ***\n");
+ Report("*** Most likely this means that the app is already ***\n");
+ Report("*** using DbgHelp, possibly with incompatible flags. ***\n");
+ Report("*** Due to technical reasons, symbolization might crash ***\n");
+ Report("*** or produce wrong results. ***\n");
+ SymCleanup(GetCurrentProcess());
+ TrySymInitialize();
+ }
+ is_dbghelp_initialized = true;
+
+ // When an executable is run from a location different from the one where it
+ // was originally built, we may not see the nearby PDB files.
+ // To work around this, let's append the directory of the main module
+ // to the symbol search path. All the failures below are not fatal.
+ const size_t kSymPathSize = 2048;
+ static wchar_t path_buffer[kSymPathSize + 1 + MAX_PATH];
+ if (!SymGetSearchPathW(GetCurrentProcess(), path_buffer, kSymPathSize)) {
+ Report("*** WARNING: Failed to SymGetSearchPathW ***\n");
+ return;
+ }
+ size_t sz = wcslen(path_buffer);
+ if (sz) {
+ CHECK_EQ(0, wcscat_s(path_buffer, L";"));
+ sz++;
}
+ DWORD res = GetModuleFileNameW(NULL, path_buffer + sz, MAX_PATH);
+ if (res == 0 || res == MAX_PATH) {
+ Report("*** WARNING: Failed to getting the EXE directory ***\n");
+ return;
+ }
+ // Write the zero character in place of the last backslash to get the
+ // directory of the main module at the end of path_buffer.
+ wchar_t *last_bslash = wcsrchr(path_buffer + sz, L'\\');
+ CHECK_NE(last_bslash, 0);
+ *last_bslash = L'\0';
+ if (!SymSetSearchPathW(GetCurrentProcess(), path_buffer)) {
+ Report("*** WARNING: Failed to SymSetSearchPathW\n");
+ return;
+ }
+}
- const char *Demangle(const char *name) override {
- CHECK(initialized_);
- static char demangle_buffer[1000];
- if (name[0] == '\01' &&
- UnDecorateSymbolName(name + 1, demangle_buffer, sizeof(demangle_buffer),
- UNDNAME_NAME_ONLY))
- return demangle_buffer;
- else
- return name;
+} // namespace
+
+bool WinSymbolizerTool::SymbolizePC(uptr addr, SymbolizedStack *frame) {
+ InitializeDbgHelpIfNeeded();
+
+ // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
+ char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
+ PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
+ symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ symbol->MaxNameLen = MAX_SYM_NAME;
+ DWORD64 offset = 0;
+ BOOL got_objname = SymFromAddr(GetCurrentProcess(),
+ (DWORD64)addr, &offset, symbol);
+ if (!got_objname)
+ return false;
+
+ DWORD unused;
+ IMAGEHLP_LINE64 line_info;
+ line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+ BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr,
+ &unused, &line_info);
+ frame->info.function = internal_strdup(symbol->Name);
+ frame->info.function_offset = (uptr)offset;
+ if (got_fileline) {
+ frame->info.file = internal_strdup(line_info.FileName);
+ frame->info.line = line_info.LineNumber;
}
+ return true;
+}
- // FIXME: Implement GetModuleNameAndOffsetForPC().
+const char *WinSymbolizerTool::Demangle(const char *name) {
+ CHECK(is_dbghelp_initialized);
+ static char demangle_buffer[1000];
+ if (name[0] == '\01' &&
+ UnDecorateSymbolName(name + 1, demangle_buffer, sizeof(demangle_buffer),
+ UNDNAME_NAME_ONLY))
+ return demangle_buffer;
+ else
+ return name;
+}
- private:
- void InitializeIfNeeded() {
- if (initialized_)
- return;
- if (!TrySymInitialize()) {
- // OK, maybe the client app has called SymInitialize already.
- // That's a bit unfortunate for us as all the DbgHelp functions are
- // single-threaded and we can't coordinate with the app.
- // FIXME: Can we stop the other threads at this point?
- // Anyways, we have to reconfigure stuff to make sure that SymInitialize
- // has all the appropriate options set.
- // Cross our fingers and reinitialize DbgHelp.
- Report("*** WARNING: Failed to initialize DbgHelp! ***\n");
- Report("*** Most likely this means that the app is already ***\n");
- Report("*** using DbgHelp, possibly with incompatible flags. ***\n");
- Report("*** Due to technical reasons, symbolization might crash ***\n");
- Report("*** or produce wrong results. ***\n");
- SymCleanup(GetCurrentProcess());
- TrySymInitialize();
- }
- initialized_ = true;
-
- // When an executable is run from a location different from the one where it
- // was originally built, we may not see the nearby PDB files.
- // To work around this, let's append the directory of the main module
- // to the symbol search path. All the failures below are not fatal.
- const size_t kSymPathSize = 2048;
- static wchar_t path_buffer[kSymPathSize + 1 + MAX_PATH];
- if (!SymGetSearchPathW(GetCurrentProcess(), path_buffer, kSymPathSize)) {
- Report("*** WARNING: Failed to SymGetSearchPathW ***\n");
- return;
- }
- size_t sz = wcslen(path_buffer);
- if (sz) {
- CHECK_EQ(0, wcscat_s(path_buffer, L";"));
- sz++;
- }
- DWORD res = GetModuleFileNameW(NULL, path_buffer + sz, MAX_PATH);
- if (res == 0 || res == MAX_PATH) {
- Report("*** WARNING: Failed to getting the EXE directory ***\n");
- return;
- }
- // Write the zero character in place of the last backslash to get the
- // directory of the main module at the end of path_buffer.
- wchar_t *last_bslash = wcsrchr(path_buffer + sz, L'\\');
- CHECK_NE(last_bslash, 0);
- *last_bslash = L'\0';
- if (!SymSetSearchPathW(GetCurrentProcess(), path_buffer)) {
- Report("*** WARNING: Failed to SymSetSearchPathW\n");
- return;
- }
- }
+bool FindModuleNameAndOffsetForAddress(uptr addr, const char **module_name,
+ uptr *module_offset) {
+ InitializeDbgHelpIfNeeded();
- bool TrySymInitialize() {
- SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
- return SymInitialize(GetCurrentProcess(), 0, TRUE);
- // FIXME: We don't call SymCleanup() on exit yet - should we?
+ IMAGEHLP_MODULE64 mod_info;
+ internal_memset(&mod_info, 0, sizeof(mod_info));
+ mod_info.SizeOfStruct = sizeof(mod_info);
+ if (SymGetModuleInfo64(GetCurrentProcess(), addr, &mod_info)) {
+ *module_name = mod_info.ImageName;
+ *module_offset = addr - (uptr)mod_info.BaseOfImage;
+ return true;
}
+ return false;
+}
- // All DbgHelp functions are single threaded, so we should use a mutex to
- // serialize accesses.
- BlockingMutex dbghelp_mu_;
- bool initialized_;
+// TODO(kuba.brecka): To be merged with POSIXSymbolizer.
+class WinSymbolizer : public Symbolizer {
+ public:
+ explicit WinSymbolizer(IntrusiveList<SymbolizerTool> tools)
+ : Symbolizer(tools) {}
+
+ private:
+ bool PlatformFindModuleNameAndOffsetForAddress(
+ uptr addr, const char **module_name, uptr *module_offset) override {
+ return ::FindModuleNameAndOffsetForAddress(addr, module_name,
+ module_offset);
+ }
+ const char *PlatformDemangle(const char *name) override { return name; }
+ void PlatformPrepareForSandboxing() override { }
};
Symbolizer *Symbolizer::PlatformInit() {
- static bool called_once = false;
- CHECK(!called_once && "Shouldn't create more than one symbolizer");
- called_once = true;
- return new(symbolizer_allocator_) WinSymbolizer();
+ IntrusiveList<SymbolizerTool> list;
+ list.clear();
+ list.push_back(new(symbolizer_allocator_) WinSymbolizerTool());
+ return new(symbolizer_allocator_) WinSymbolizer(list);
}
} // namespace __sanitizer
diff --git a/lib/sanitizer_common/sanitizer_symbolizer_win.h b/lib/sanitizer_common/sanitizer_symbolizer_win.h
new file mode 100644
index 000000000..72ac5e5ee
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_symbolizer_win.h
@@ -0,0 +1,31 @@
+//===-- sanitizer_symbolizer_win.h ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Header file for the Windows symbolizer tool.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SYMBOLIZER_WIN_H
+#define SANITIZER_SYMBOLIZER_WIN_H
+
+#include "sanitizer_symbolizer_internal.h"
+
+namespace __sanitizer {
+
+class WinSymbolizerTool : public SymbolizerTool {
+ public:
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
+ bool SymbolizeData(uptr addr, DataInfo *info) override {
+ return false;
+ }
+ const char *Demangle(const char *name) override;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SYMBOLIZER_WIN_H
diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc
index 335cecabe..3ec90842c 100644
--- a/lib/sanitizer_common/sanitizer_win.cc
+++ b/lib/sanitizer_common/sanitizer_win.cc
@@ -313,6 +313,19 @@ char *FindPathToBinary(const char *name) {
return 0;
}
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
+ // Nothing here for now.
+ return 0;
+}
+
+bool IsPathSeparator(const char c) {
+ return c == '\\' || c == '/';
+}
+
+bool IsAbsolutePath(const char *path) {
+ UNIMPLEMENTED();
+}
+
void SleepForSeconds(int seconds) {
Sleep(seconds * 1000);
}
@@ -368,7 +381,7 @@ uptr internal_open(const char *filename, int flags, u32 mode) {
UNIMPLEMENTED();
}
-uptr OpenFile(const char *filename, bool write) {
+uptr OpenFile(const char *filename, FileAccessMode mode) {
UNIMPLEMENTED();
}
@@ -618,6 +631,23 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
return true;
}
+SignalContext SignalContext::Create(void *siginfo, void *context) {
+ EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD*)siginfo;
+ CONTEXT *context_record = (CONTEXT*)context;
+
+ uptr pc = (uptr)exception_record->ExceptionAddress;
+#ifdef _WIN64
+ uptr bp = (uptr)context_record->Rbp;
+ uptr sp = (uptr)context_record->Rsp;
+#else
+ uptr bp = (uptr)context_record->Ebp;
+ uptr sp = (uptr)context_record->Esp;
+#endif
+ uptr access_addr = exception_record->ExceptionInformation[1];
+
+ return SignalContext(context, access_addr, pc, sp, bp);
+}
+
} // namespace __sanitizer
#endif // _WIN32
diff --git a/lib/sanitizer_common/scripts/check_lint.sh b/lib/sanitizer_common/scripts/check_lint.sh
index 7ed05d735..9108a81e2 100755
--- a/lib/sanitizer_common/scripts/check_lint.sh
+++ b/lib/sanitizer_common/scripts/check_lint.sh
@@ -17,7 +17,6 @@ fi
# Filters
# TODO: remove some of these filters
-LLVM_LINT_FILTER=-,+whitespace
COMMON_LINT_FILTER=-build/include,-build/header_guard,-legal/copyright,-whitespace/comments,-readability/casting,\
-build/namespaces
ASAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/int
@@ -60,9 +59,6 @@ run_lint() {
${LITLINT} "$@" 2>>$ERROR_LOG
}
-run_lint ${LLVM_LINT_FILTER} --filter=${LLVM_LINT_FILTER} \
- lib/Transforms/Instrumentation/*Sanitizer.cpp &
-
if [ "${COMPILER_RT}" = "" ]; then
COMPILER_RT=projects/compiler-rt
fi
diff --git a/lib/sanitizer_common/scripts/sancov.py b/lib/sanitizer_common/scripts/sancov.py
index 566116eb2..53180d09b 100755
--- a/lib/sanitizer_common/scripts/sancov.py
+++ b/lib/sanitizer_common/scripts/sancov.py
@@ -9,35 +9,77 @@ import sys
import bisect
import os.path
-prog_name = "";
+prog_name = ""
def Usage():
print >> sys.stderr, "Usage: \n" + \
- " " + prog_name + " merge file1 [file2 ...] > output\n" \
- " " + prog_name + " print file1 [file2 ...]\n" \
- " " + prog_name + " unpack file1 [file2 ...]\n" \
- " " + prog_name + " rawunpack file1 [file2 ...]\n"
+ " " + prog_name + " [32|64] merge file1 [file2 ...] > output\n" \
+ " " + prog_name + " [32|64] print file1 [file2 ...]\n" \
+ " " + prog_name + " [32|64] unpack file1 [file2 ...]\n" \
+ " " + prog_name + " [32|64] rawunpack file1 [file2 ...]\n"
exit(1)
+def CheckBits(bits):
+ if bits != 32 and bits != 64:
+ raise Exception("Wrong bitness: %d" % bits)
+
+def TypeCodeForBits(bits):
+ CheckBits(bits)
+ return 'L' if bits == 64 else 'I'
+
+kMagic32SecondHalf = 0xFFFFFF32;
+kMagic64SecondHalf = 0xFFFFFF64;
+kMagicFirstHalf = 0xC0BFFFFF;
+
+def MagicForBits(bits):
+ CheckBits(bits)
+ if sys.byteorder == 'little':
+ return [kMagic64SecondHalf if bits == 64 else kMagic32SecondHalf, kMagicFirstHalf]
+ else:
+ return [kMagicFirstHalf, kMagic64SecondHalf if bits == 64 else kMagic32SecondHalf]
+
+def ReadMagicAndReturnBitness(f, path):
+ magic_bytes = f.read(8)
+ magic_words = struct.unpack('II', magic_bytes);
+ bits = 0
+ idx = 1 if sys.byteorder == 'little' else 0
+ if magic_words[idx] == kMagicFirstHalf:
+ if magic_words[1-idx] == kMagic64SecondHalf:
+ bits = 64
+ elif magic_words[1-idx] == kMagic32SecondHalf:
+ bits = 32
+ if bits == 0:
+ raise Exception('Bad magic word in %s' % path)
+ return bits
+
def ReadOneFile(path):
with open(path, mode="rb") as f:
f.seek(0, 2)
size = f.tell()
f.seek(0, 0)
- s = set(array.array('I', f.read(size)))
- print >>sys.stderr, "%s: read %d PCs from %s" % (prog_name, size / 4, path)
+ if size < 8:
+ raise Exception('File %s is short (< 8 bytes)' % path)
+ bits = ReadMagicAndReturnBitness(f, path)
+ size -= 8
+ s = array.array(TypeCodeForBits(bits), f.read(size))
+ print >>sys.stderr, "%s: read %d %d-bit PCs from %s" % (prog_name, size * 8 / bits, bits, path)
return s
def Merge(files):
s = set()
for f in files:
- s = s.union(ReadOneFile(f))
+ s = s.union(set(ReadOneFile(f)))
print >> sys.stderr, "%s: %d files merged; %d PCs total" % \
(prog_name, len(files), len(s))
return sorted(s)
def PrintFiles(files):
- s = Merge(files)
+ if len(files) > 1:
+ s = Merge(files)
+ else: # If there is just on file, print the PCs in order.
+ s = ReadOneFile(files[0])
+ print >> sys.stderr, "%s: 1 file merged; %d PCs total" % \
+ (prog_name, len(s))
for i in s:
print "0x%x" % i
@@ -45,7 +87,11 @@ def MergeAndPrint(files):
if sys.stdout.isatty():
Usage()
s = Merge(files)
- a = array.array('I', s)
+ bits = 32
+ if max(s) > 0xFFFFFFFF:
+ bits = 64
+ array.array('I', MagicForBits(bits)).tofile(sys.stdout)
+ a = array.array(TypeCodeForBits(bits), s)
a.tofile(sys.stdout)
@@ -82,6 +128,8 @@ def UnpackOneRawFile(path, map_path):
with open(map_path, mode="rt") as f_map:
print >> sys.stderr, "%s: reading map %s" % (prog_name, map_path)
bits = int(f_map.readline())
+ if bits != 32 and bits != 64:
+ raise Exception('Wrong bits size in the map')
for line in f_map:
parts = line.rstrip().split()
mem_map.append((int(parts[0], 16),
@@ -97,11 +145,7 @@ def UnpackOneRawFile(path, map_path):
f.seek(0, 2)
size = f.tell()
f.seek(0, 0)
- if bits == 64:
- typecode = 'L'
- else:
- typecode = 'I'
- pcs = array.array(typecode, f.read(size))
+ pcs = array.array(TypeCodeForBits(bits), f.read(size))
mem_map_pcs = [[] for i in range(0, len(mem_map))]
for pc in pcs:
@@ -119,9 +163,10 @@ def UnpackOneRawFile(path, map_path):
assert path.endswith('.sancov.raw')
dst_path = module_path + '.' + os.path.basename(path)[:-4]
print >> sys.stderr, "%s: writing %d PCs to %s" % (prog_name, len(pc_list), dst_path)
- arr = array.array('I')
+ arr = array.array(TypeCodeForBits(bits))
arr.fromlist(sorted(pc_list))
with open(dst_path, 'ab') as f2:
+ array.array('I', MagicForBits(bits)).tofile(f2)
arr.tofile(f2)
def RawUnpack(files):
@@ -135,6 +180,7 @@ if __name__ == '__main__':
prog_name = sys.argv[0]
if len(sys.argv) <= 2:
Usage();
+
if sys.argv[1] == "print":
PrintFiles(sys.argv[2:])
elif sys.argv[1] == "merge":
diff --git a/lib/sanitizer_common/tests/CMakeLists.txt b/lib/sanitizer_common/tests/CMakeLists.txt
index 75008db3b..b062c5a02 100644
--- a/lib/sanitizer_common/tests/CMakeLists.txt
+++ b/lib/sanitizer_common/tests/CMakeLists.txt
@@ -28,6 +28,7 @@ set(SANITIZER_UNITTESTS
sanitizer_stacktrace_test.cc
sanitizer_stoptheworld_test.cc
sanitizer_suppressions_test.cc
+ sanitizer_symbolizer_test.cc
sanitizer_test_main.cc
sanitizer_thread_registry_test.cc)
diff --git a/lib/sanitizer_common/tests/sanitizer_libc_test.cc b/lib/sanitizer_common/tests/sanitizer_libc_test.cc
index 8712d2c1b..279f6fed9 100644
--- a/lib/sanitizer_common/tests/sanitizer_libc_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_libc_test.cc
@@ -78,14 +78,14 @@ TEST(SanitizerCommon, FileOps) {
char tmpfile[128];
temp_file_name(tmpfile, sizeof(tmpfile), "sanitizer_common.fileops.tmp.");
- uptr openrv = OpenFile(tmpfile, true);
+ uptr openrv = OpenFile(tmpfile, WrOnly);
EXPECT_FALSE(internal_iserror(openrv));
fd_t fd = openrv;
EXPECT_EQ(len1, internal_write(fd, str1, len1));
EXPECT_EQ(len2, internal_write(fd, str2, len2));
internal_close(fd);
- openrv = OpenFile(tmpfile, false);
+ openrv = OpenFile(tmpfile, RdOnly);
EXPECT_FALSE(internal_iserror(openrv));
fd = openrv;
uptr fsize = internal_filesize(fd);
@@ -134,7 +134,7 @@ TEST(SanitizerCommon, InternalMmapWithOffset) {
char tmpfile[128];
temp_file_name(tmpfile, sizeof(tmpfile),
"sanitizer_common.internalmmapwithoffset.tmp.");
- uptr res = OpenFile(tmpfile, true);
+ uptr res = OpenFile(tmpfile, RdWr);
ASSERT_FALSE(internal_iserror(res));
fd_t fd = res;
diff --git a/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc b/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc
index ac820c25a..a8bd7261e 100644
--- a/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc
@@ -30,11 +30,11 @@ class FastUnwindTest : public ::testing::Test {
}
void *mapping;
- uptr *fake_stack;
+ uhwptr *fake_stack;
const uptr fake_stack_size = 10;
- uptr start_pc;
- uptr fake_top;
- uptr fake_bottom;
+ uhwptr start_pc;
+ uhwptr fake_top;
+ uhwptr fake_bottom;
BufferedStackTrace trace;
};
@@ -48,7 +48,7 @@ void FastUnwindTest::SetUp() {
Mprotect((uptr)mapping, ps);
// Unwinder may peek 1 word down from the starting FP.
- fake_stack = (uptr *)((uptr)mapping + ps + sizeof(uptr));
+ fake_stack = (uhwptr *)((uptr)mapping + ps + sizeof(uhwptr));
// Fill an array of pointers with fake fp+retaddr pairs. Frame pointers have
// even indices.
@@ -57,12 +57,12 @@ void FastUnwindTest::SetUp() {
fake_stack[i+1] = PC(i + 1); // retaddr
}
// Mark the last fp point back up to terminate the stack trace.
- fake_stack[RoundDownTo(fake_stack_size - 1, 2)] = (uptr)&fake_stack[0];
+ fake_stack[RoundDownTo(fake_stack_size - 1, 2)] = (uhwptr)&fake_stack[0];
// Top is two slots past the end because FastUnwindStack subtracts two.
- fake_top = (uptr)&fake_stack[fake_stack_size + 2];
+ fake_top = (uhwptr)&fake_stack[fake_stack_size + 2];
// Bottom is one slot before the start because FastUnwindStack uses >.
- fake_bottom = (uptr)mapping;
+ fake_bottom = (uhwptr)mapping;
start_pc = PC(0);
}
@@ -85,7 +85,7 @@ TEST_F(FastUnwindTest, Basic) {
// From: http://code.google.com/p/address-sanitizer/issues/detail?id=162
TEST_F(FastUnwindTest, FramePointerLoop) {
// Make one fp point to itself.
- fake_stack[4] = (uptr)&fake_stack[4];
+ fake_stack[4] = (uhwptr)&fake_stack[4];
if (!TryFastUnwind(kStackTraceMax))
return;
// Should get all on-stack retaddrs up to the 4th slot and start_pc.
@@ -114,7 +114,7 @@ TEST_F(FastUnwindTest, OneFrameStackTrace) {
return;
EXPECT_EQ(1U, trace.size);
EXPECT_EQ(start_pc, trace.trace[0]);
- EXPECT_EQ((uptr)&fake_stack[0], trace.top_frame_bp);
+ EXPECT_EQ((uhwptr)&fake_stack[0], trace.top_frame_bp);
}
TEST_F(FastUnwindTest, ZeroFramesStackTrace) {
@@ -127,7 +127,7 @@ TEST_F(FastUnwindTest, ZeroFramesStackTrace) {
TEST_F(FastUnwindTest, FPBelowPrevFP) {
// The next FP points to unreadable memory inside the stack limits, but below
// current FP.
- fake_stack[0] = (uptr)&fake_stack[-50];
+ fake_stack[0] = (uhwptr)&fake_stack[-50];
fake_stack[1] = PC(1);
if (!TryFastUnwind(3))
return;
diff --git a/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc b/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc
index b6786ba8b..802af392c 100644
--- a/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc
@@ -189,6 +189,16 @@ TEST(StopTheWorld, SuspendThreadsAdvanced) {
pthread_mutex_destroy(&advanced_incrementer_thread_exit_mutex);
}
+static void SegvCallback(const SuspendedThreadsList &suspended_threads_list,
+ void *argument) {
+ *(volatile int*)0x1234 = 0;
+}
+
+TEST(StopTheWorld, SegvInCallback) {
+ // Test that tracer thread catches SIGSEGV.
+ StopTheWorld(&SegvCallback, NULL);
+}
+
} // namespace __sanitizer
#endif // SANITIZER_LINUX && defined(__x86_64__)
diff --git a/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc b/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc
new file mode 100644
index 000000000..429ac591e
--- /dev/null
+++ b/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc
@@ -0,0 +1,58 @@
+//===-- sanitizer_symbolizer_test.cc --------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Tests for sanitizer_symbolizer.h and sanitizer_symbolizer_internal.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_allocator_internal.h"
+#include "sanitizer_common/sanitizer_symbolizer_internal.h"
+#include "gtest/gtest.h"
+
+namespace __sanitizer {
+
+TEST(Symbolizer, ExtractToken) {
+ char *token;
+ const char *rest;
+
+ rest = ExtractToken("a;b;c", ";", &token);
+ EXPECT_STREQ("a", token);
+ EXPECT_STREQ("b;c", rest);
+ InternalFree(token);
+
+ rest = ExtractToken("aaa-bbb.ccc", ";.-*", &token);
+ EXPECT_STREQ("aaa", token);
+ EXPECT_STREQ("bbb.ccc", rest);
+ InternalFree(token);
+}
+
+TEST(Symbolizer, ExtractInt) {
+ int token;
+ const char *rest = ExtractInt("123,456;789", ";,", &token);
+ EXPECT_EQ(123, token);
+ EXPECT_STREQ("456;789", rest);
+}
+
+TEST(Symbolizer, ExtractUptr) {
+ uptr token;
+ const char *rest = ExtractUptr("123,456;789", ";,", &token);
+ EXPECT_EQ(123U, token);
+ EXPECT_STREQ("456;789", rest);
+}
+
+TEST(Symbolizer, ExtractTokenUpToDelimiter) {
+ char *token;
+ const char *rest =
+ ExtractTokenUpToDelimiter("aaa-+-bbb-+-ccc", "-+-", &token);
+ EXPECT_STREQ("aaa", token);
+ EXPECT_STREQ("bbb-+-ccc", rest);
+ InternalFree(token);
+}
+
+} // namespace __sanitizer
diff --git a/lib/tsan/Makefile.old b/lib/tsan/Makefile.old
index 9e0693fa0..fbdb9ddad 100644
--- a/lib/tsan/Makefile.old
+++ b/lib/tsan/Makefile.old
@@ -11,7 +11,9 @@ ifeq ($(DEBUG), 0)
CXXFLAGS += -O3
endif
ifeq ($(CXX), $(CLANG)++)
- CXXFLAGS+= -Wno-unused-private-field -Wno-static-in-inline -Wgnu
+ CXXFLAGS += -Wno-unused-private-field -Wno-static-in-inline -Wgnu
+else
+ CXXFLAGS += -Wno-maybe-uninitialized
endif
LIBTSAN=rtl/libtsan.a
diff --git a/lib/tsan/rtl/Makefile.old b/lib/tsan/rtl/Makefile.old
index 150b37634..627e03bdc 100644
--- a/lib/tsan/rtl/Makefile.old
+++ b/lib/tsan/rtl/Makefile.old
@@ -15,6 +15,7 @@ CXXFLAGS+=$(CFLAGS)
ifeq ($(DEBUG), 0)
CXXFLAGS+=-fomit-frame-pointer
ifeq ($(CXX), g++)
+ CXXFLAGS+=-Wno-maybe-uninitialized
CXXFLAGS+=-Wframe-larger-than=512
endif # CXX=g++
endif # DEBUG=0
diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc
index 31ff7d56a..c45bcdc1c 100644
--- a/lib/tsan/rtl/tsan_interceptors.cc
+++ b/lib/tsan/rtl/tsan_interceptors.cc
@@ -145,7 +145,10 @@ struct sigaction_t {
const sighandler_t SIG_DFL = (sighandler_t)0;
const sighandler_t SIG_IGN = (sighandler_t)1;
const sighandler_t SIG_ERR = (sighandler_t)-1;
-#ifdef __mips__
+#if SANITIZER_FREEBSD
+const int SA_SIGINFO = 0x40;
+const int SIG_SETMASK = 3;
+#elif defined(__mips__)
const int SA_SIGINFO = 8;
const int SIG_SETMASK = 3;
#else
@@ -167,7 +170,7 @@ struct SignalDesc {
ucontext_t ctx;
};
-struct SignalContext {
+struct ThreadSignalContext {
int int_signal_send;
atomic_uintptr_t in_blocking_func;
atomic_uintptr_t have_pending_signals;
@@ -194,10 +197,10 @@ void InitializeLibIgnore() {
} // namespace __tsan
-static SignalContext *SigCtx(ThreadState *thr) {
- SignalContext *ctx = (SignalContext*)thr->signal_ctx;
+static ThreadSignalContext *SigCtx(ThreadState *thr) {
+ ThreadSignalContext *ctx = (ThreadSignalContext*)thr->signal_ctx;
if (ctx == 0 && !thr->is_dead) {
- ctx = (SignalContext*)MmapOrDie(sizeof(*ctx), "SignalContext");
+ ctx = (ThreadSignalContext*)MmapOrDie(sizeof(*ctx), "ThreadSignalContext");
MemoryResetRange(thr, (uptr)&SigCtx, (uptr)ctx, sizeof(*ctx));
thr->signal_ctx = ctx;
}
@@ -298,7 +301,7 @@ struct BlockingCall {
}
ThreadState *thr;
- SignalContext *ctx;
+ ThreadSignalContext *ctx;
};
TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
@@ -410,7 +413,7 @@ static void JmpBufGarbageCollect(ThreadState *thr, uptr sp) {
}
static void SetJmp(ThreadState *thr, uptr sp, uptr mangled_sp) {
- if (thr->shadow_stack_pos == 0) // called from libc guts during bootstrap
+ if (!thr->is_inited) // called from libc guts during bootstrap
return;
// Cleanup old bufs.
JmpBufGarbageCollect(thr, sp);
@@ -419,7 +422,7 @@ static void SetJmp(ThreadState *thr, uptr sp, uptr mangled_sp) {
buf->sp = sp;
buf->mangled_sp = mangled_sp;
buf->shadow_stack_pos = thr->shadow_stack_pos;
- SignalContext *sctx = SigCtx(thr);
+ ThreadSignalContext *sctx = SigCtx(thr);
buf->int_signal_send = sctx ? sctx->int_signal_send : 0;
buf->in_blocking_func = sctx ?
atomic_load(&sctx->in_blocking_func, memory_order_relaxed) :
@@ -442,7 +445,7 @@ static void LongJmp(ThreadState *thr, uptr *env) {
// Unwind the stack.
while (thr->shadow_stack_pos > buf->shadow_stack_pos)
FuncExit(thr);
- SignalContext *sctx = SigCtx(thr);
+ ThreadSignalContext *sctx = SigCtx(thr);
if (sctx) {
sctx->int_signal_send = buf->int_signal_send;
atomic_store(&sctx->in_blocking_func, buf->in_blocking_func,
@@ -666,9 +669,12 @@ TSAN_INTERCEPTOR(void*, memset, void *dst, int v, uptr size) {
}
TSAN_INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) {
- SCOPED_TSAN_INTERCEPTOR(memcpy, dst, src, size);
- MemoryAccessRange(thr, pc, (uptr)dst, size, true);
- MemoryAccessRange(thr, pc, (uptr)src, size, false);
+ // On FreeBSD we get here from libthr internals on thread initialization.
+ if (cur_thread()->is_inited) {
+ SCOPED_TSAN_INTERCEPTOR(memcpy, dst, src, size);
+ MemoryAccessRange(thr, pc, (uptr)dst, size, true);
+ MemoryAccessRange(thr, pc, (uptr)src, size, false);
+ }
return internal_memcpy(dst, src, size);
}
@@ -797,6 +803,7 @@ TSAN_INTERCEPTOR(void*, mmap64, void *addr, long_t sz, int prot,
TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) {
SCOPED_TSAN_INTERCEPTOR(munmap, addr, sz);
DontNeedShadowFor((uptr)addr, sz);
+ ctx->metamap.ResetRange(thr, pc, (uptr)addr, (uptr)sz);
int res = REAL(munmap)(addr, sz);
return res;
}
@@ -878,7 +885,7 @@ static void thread_finalize(void *v) {
{
ThreadState *thr = cur_thread();
ThreadFinish(thr);
- SignalContext *sctx = thr->signal_ctx;
+ ThreadSignalContext *sctx = thr->signal_ctx;
if (sctx) {
thr->signal_ctx = 0;
UnmapOrDie(sctx, sizeof(*sctx));
@@ -1940,7 +1947,7 @@ static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
}
void ProcessPendingSignals(ThreadState *thr) {
- SignalContext *sctx = SigCtx(thr);
+ ThreadSignalContext *sctx = SigCtx(thr);
if (sctx == 0 ||
atomic_load(&sctx->have_pending_signals, memory_order_relaxed) == 0)
return;
@@ -1948,8 +1955,8 @@ void ProcessPendingSignals(ThreadState *thr) {
atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
// These are too big for stack.
static THREADLOCAL __sanitizer_sigset_t emptyset, oldset;
- REAL(sigfillset)(&emptyset);
- pthread_sigmask(SIG_SETMASK, &emptyset, &oldset);
+ CHECK_EQ(0, REAL(sigfillset)(&emptyset));
+ CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &emptyset, &oldset));
for (int sig = 0; sig < kSigCount; sig++) {
SignalDesc *signal = &sctx->pending_signals[sig];
if (signal->armed) {
@@ -1958,13 +1965,13 @@ void ProcessPendingSignals(ThreadState *thr) {
&signal->siginfo, &signal->ctx);
}
}
- pthread_sigmask(SIG_SETMASK, &oldset, 0);
+ CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &oldset, 0));
atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
}
} // namespace __tsan
-static bool is_sync_signal(SignalContext *sctx, int sig) {
+static bool is_sync_signal(ThreadSignalContext *sctx, int sig) {
return sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS ||
// If we are sending signal to ourselves, we must process it now.
@@ -1974,7 +1981,7 @@ static bool is_sync_signal(SignalContext *sctx, int sig) {
void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
my_siginfo_t *info, void *ctx) {
ThreadState *thr = cur_thread();
- SignalContext *sctx = SigCtx(thr);
+ ThreadSignalContext *sctx = SigCtx(thr);
if (sig < 0 || sig >= kSigCount) {
VPrintf(1, "ThreadSanitizer: ignoring signal %d\n", sig);
return;
@@ -2083,7 +2090,7 @@ TSAN_INTERCEPTOR(int, sigsuspend, const __sanitizer_sigset_t *mask) {
TSAN_INTERCEPTOR(int, raise, int sig) {
SCOPED_TSAN_INTERCEPTOR(raise, sig);
- SignalContext *sctx = SigCtx(thr);
+ ThreadSignalContext *sctx = SigCtx(thr);
CHECK_NE(sctx, 0);
int prev = sctx->int_signal_send;
sctx->int_signal_send = sig;
@@ -2095,7 +2102,7 @@ TSAN_INTERCEPTOR(int, raise, int sig) {
TSAN_INTERCEPTOR(int, kill, int pid, int sig) {
SCOPED_TSAN_INTERCEPTOR(kill, pid, sig);
- SignalContext *sctx = SigCtx(thr);
+ ThreadSignalContext *sctx = SigCtx(thr);
CHECK_NE(sctx, 0);
int prev = sctx->int_signal_send;
if (pid == (int)internal_getpid()) {
@@ -2111,7 +2118,7 @@ TSAN_INTERCEPTOR(int, kill, int pid, int sig) {
TSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) {
SCOPED_TSAN_INTERCEPTOR(pthread_kill, tid, sig);
- SignalContext *sctx = SigCtx(thr);
+ ThreadSignalContext *sctx = SigCtx(thr);
CHECK_NE(sctx, 0);
int prev = sctx->int_signal_send;
if (tid == pthread_self()) {
diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc
index 7e69cb4ec..18bad146b 100644
--- a/lib/tsan/rtl/tsan_report.cc
+++ b/lib/tsan/rtl/tsan_report.cc
@@ -335,10 +335,8 @@ void PrintReport(const ReportDesc *rep) {
Printf(" And %d more similar thread leaks.\n\n", rep->count - 1);
if (ReportStack *stack = ChooseSummaryStack(rep)) {
- if (SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames)) {
- const AddressInfo &info = frame->info;
- ReportErrorSummary(rep_typ_str, info.file, info.line, info.function);
- }
+ if (SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames))
+ ReportErrorSummary(rep_typ_str, frame->info);
}
Printf("==================\n");
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index b76f3e05d..1c64caf1c 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/lib/tsan/rtl/tsan_rtl.cc
@@ -153,7 +153,7 @@ static void BackgroundThread(void *arg) {
} else {
InternalScopedString filename(kMaxPathLength);
filename.append("%s.%d", flags()->profile_memory, (int)internal_getpid());
- uptr openrv = OpenFile(filename.data(), true);
+ uptr openrv = OpenFile(filename.data(), WrOnly);
if (internal_iserror(openrv)) {
Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
&filename[0]);
@@ -461,7 +461,7 @@ void GrowShadowStack(ThreadState *thr) {
#endif
u32 CurrentStackId(ThreadState *thr, uptr pc) {
- if (thr->shadow_stack_pos == 0) // May happen during bootstrap.
+ if (!thr->is_inited) // May happen during bootstrap.
return 0;
if (pc != 0) {
#ifndef SANITIZER_GO
diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h
index 7a60e5c55..d32688ee6 100644
--- a/lib/tsan/rtl/tsan_rtl.h
+++ b/lib/tsan/rtl/tsan_rtl.h
@@ -313,7 +313,7 @@ class Shadow : public FastState {
}
};
-struct SignalContext;
+struct ThreadSignalContext;
struct JmpBuf {
uptr sp;
@@ -371,6 +371,7 @@ struct ThreadState {
const int unique_id;
bool in_symbolizer;
bool in_ignored_lib;
+ bool is_inited;
bool is_dead;
bool is_freeing;
bool is_vptr_access;
@@ -387,7 +388,7 @@ struct ThreadState {
DDLogicalThread *dd_lt;
atomic_uintptr_t in_signal_handler;
- SignalContext *signal_ctx;
+ ThreadSignalContext *signal_ctx;
DenseSlabAllocCache block_cache;
DenseSlabAllocCache sync_cache;
diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc
index 8ed1fbf2e..66c78cfdd 100644
--- a/lib/tsan/rtl/tsan_rtl_thread.cc
+++ b/lib/tsan/rtl/tsan_rtl_thread.cc
@@ -120,6 +120,7 @@ void ThreadContext::OnStarted(void *arg) {
AcquireImpl(thr, 0, &sync);
StatInc(thr, StatSyncAcquire);
sync.Reset(&thr->clock_cache);
+ thr->is_inited = true;
DPrintf("#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx "
"tls_addr=%zx tls_size=%zx\n",
tid, (uptr)epoch0, args->stk_addr, args->stk_size,
diff --git a/lib/tsan/rtl/tsan_suppressions.cc b/lib/tsan/rtl/tsan_suppressions.cc
index 5413f04af..731572980 100644
--- a/lib/tsan/rtl/tsan_suppressions.cc
+++ b/lib/tsan/rtl/tsan_suppressions.cc
@@ -21,6 +21,7 @@
#include "tsan_mman.h"
#include "tsan_platform.h"
+#ifndef SANITIZER_GO
// Suppressions for true/false positives in standard libraries.
static const char *const std_suppressions =
// Libstdc++ 4.4 has data races in std::string.
@@ -33,7 +34,6 @@ static const char *const std_suppressions =
"race:std::_Sp_counted_ptr_inplace<std::thread::_Impl\n";
// Can be overriden in frontend.
-#ifndef SANITIZER_GO
extern "C" const char *WEAK __tsan_default_suppressions() {
return 0;
}
diff --git a/lib/tsan/rtl/tsan_sync.cc b/lib/tsan/rtl/tsan_sync.cc
index 1041073be..49c4d15e5 100644
--- a/lib/tsan/rtl/tsan_sync.cc
+++ b/lib/tsan/rtl/tsan_sync.cc
@@ -80,7 +80,8 @@ uptr MetaMap::FreeBlock(ThreadState *thr, uptr pc, uptr p) {
return sz;
}
-void MetaMap::FreeRange(ThreadState *thr, uptr pc, uptr p, uptr sz) {
+bool MetaMap::FreeRange(ThreadState *thr, uptr pc, uptr p, uptr sz) {
+ bool has_something = false;
u32 *meta = MemToMeta(p);
u32 *end = MemToMeta(p + sz);
if (end == meta)
@@ -91,6 +92,7 @@ void MetaMap::FreeRange(ThreadState *thr, uptr pc, uptr p, uptr sz) {
for (;;) {
if (idx == 0)
break;
+ has_something = true;
if (idx & kFlagBlock) {
block_alloc_.Free(&thr->block_cache, idx & ~kFlagMask);
break;
@@ -106,6 +108,64 @@ void MetaMap::FreeRange(ThreadState *thr, uptr pc, uptr p, uptr sz) {
}
}
}
+ return has_something;
+}
+
+// ResetRange removes all meta objects from the range.
+// It is called for large mmap-ed regions. The function is best-effort wrt
+// freeing of meta objects, because we don't want to page in the whole range
+// which can be huge. The function probes pages one-by-one until it finds a page
+// without meta objects, at this point it stops freeing meta objects. Because
+// thread stacks grow top-down, we do the same starting from end as well.
+void MetaMap::ResetRange(ThreadState *thr, uptr pc, uptr p, uptr sz) {
+ const uptr kMetaRatio = kMetaShadowCell / kMetaShadowSize;
+ const uptr kPageSize = GetPageSizeCached() * kMetaRatio;
+ if (sz <= 4 * kPageSize) {
+ // If the range is small, just do the normal free procedure.
+ FreeRange(thr, pc, p, sz);
+ return;
+ }
+ // First, round both ends of the range to page size.
+ uptr diff = RoundUp(p, kPageSize) - p;
+ if (diff != 0) {
+ FreeRange(thr, pc, p, diff);
+ p += diff;
+ sz -= diff;
+ }
+ diff = p + sz - RoundDown(p + sz, kPageSize);
+ if (diff != 0) {
+ FreeRange(thr, pc, p + sz - diff, diff);
+ sz -= diff;
+ }
+ // Now we must have a non-empty page-aligned range.
+ CHECK_GT(sz, 0);
+ CHECK_EQ(p, RoundUp(p, kPageSize));
+ CHECK_EQ(sz, RoundUp(sz, kPageSize));
+ const uptr p0 = p;
+ const uptr sz0 = sz;
+ // Probe start of the range.
+ while (sz > 0) {
+ bool has_something = FreeRange(thr, pc, p, kPageSize);
+ p += kPageSize;
+ sz -= kPageSize;
+ if (!has_something)
+ break;
+ }
+ // Probe end of the range.
+ while (sz > 0) {
+ bool has_something = FreeRange(thr, pc, p - kPageSize, kPageSize);
+ sz -= kPageSize;
+ if (!has_something)
+ break;
+ }
+ // Finally, page out the whole range (including the parts that we've just
+ // freed). Note: we can't simply madvise, because we need to leave a zeroed
+ // range (otherwise __tsan_java_move can crash if it encounters a left-over
+ // meta objects in java heap).
+ uptr metap = (uptr)MemToMeta(p0);
+ uptr metasz = sz0 / kMetaRatio;
+ UnmapOrDie((void*)metap, metasz);
+ MmapFixedNoReserve(metap, metasz);
}
MBlock* MetaMap::GetBlock(uptr p) {
diff --git a/lib/tsan/rtl/tsan_sync.h b/lib/tsan/rtl/tsan_sync.h
index 574810d8a..2d12cdff8 100644
--- a/lib/tsan/rtl/tsan_sync.h
+++ b/lib/tsan/rtl/tsan_sync.h
@@ -73,7 +73,8 @@ class MetaMap {
void AllocBlock(ThreadState *thr, uptr pc, uptr p, uptr sz);
uptr FreeBlock(ThreadState *thr, uptr pc, uptr p);
- void FreeRange(ThreadState *thr, uptr pc, uptr p, uptr sz);
+ bool FreeRange(ThreadState *thr, uptr pc, uptr p, uptr sz);
+ void ResetRange(ThreadState *thr, uptr pc, uptr p, uptr sz);
MBlock* GetBlock(uptr p);
SyncVar* GetOrCreateAndLock(ThreadState *thr, uptr pc,
diff --git a/lib/ubsan/CMakeLists.txt b/lib/ubsan/CMakeLists.txt
index 668327296..a8b3f61ef 100644
--- a/lib/ubsan/CMakeLists.txt
+++ b/lib/ubsan/CMakeLists.txt
@@ -22,34 +22,61 @@ set(UBSAN_CXXFLAGS ${SANITIZER_COMMON_CFLAGS})
add_custom_target(ubsan)
if(APPLE)
- # Build universal binary on APPLE.
- add_compiler_rt_osx_static_runtime(clang_rt.ubsan_osx
- ARCH ${UBSAN_SUPPORTED_ARCH}
- SOURCES ${UBSAN_SOURCES} ${UBSAN_CXX_SOURCES}
- $<TARGET_OBJECTS:RTSanitizerCommon.osx>
- CFLAGS ${UBSAN_CXXFLAGS})
- add_dependencies(ubsan clang_rt.ubsan_osx)
+ foreach(os ${SANITIZER_COMMON_SUPPORTED_DARWIN_OS})
+ add_compiler_rt_darwin_object_library(RTUbsan ${os}
+ ARCH ${UBSAN_SUPPORTED_ARCH}
+ SOURCES ${UBSAN_SOURCES} ${UBSAN_CXX_SOURCES}
+ CFLAGS ${UBSAN_CXXFLAGS})
+
+ add_compiler_rt_darwin_dynamic_runtime(clang_rt.ubsan_${os}_dynamic ${os}
+ ARCH ${UBSAN_SUPPORTED_ARCH}
+ SOURCES $<TARGET_OBJECTS:RTUbsan.${os}>
+ $<TARGET_OBJECTS:RTSanitizerCommon.${os}>
+ LINKFLAGS -lc++abi)
+
+ add_dependencies(ubsan clang_rt.ubsan_${os}_dynamic)
+ endforeach()
else()
# Build separate libraries for each target.
foreach(arch ${UBSAN_SUPPORTED_ARCH})
- # Main UBSan runtime.
+ add_compiler_rt_object_library(RTUbsan ${arch}
+ SOURCES ${UBSAN_SOURCES} CFLAGS ${UBSAN_CFLAGS})
+ # C++-specific parts of UBSan runtime. Requires a C++ ABI library.
+ add_compiler_rt_object_library(RTUbsan_cxx ${arch}
+ SOURCES ${UBSAN_CXX_SOURCES} CFLAGS ${UBSAN_CXXFLAGS})
+
+ # Standalone UBSan runtimes.
+ add_compiler_rt_runtime(clang_rt.ubsan_standalone-${arch} ${arch} STATIC
+ SOURCES $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
+ $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
+ $<TARGET_OBJECTS:RTUbsan.${arch}>
+ CFLAGS ${UBSAN_CFLAGS})
+ add_compiler_rt_runtime(clang_rt.ubsan_standalone_cxx-${arch} ${arch} STATIC
+ SOURCES $<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
+ CFLAGS ${UBSAN_CXXFLAGS})
+ # UBSan runtimes used when another sanitizer is available.
add_compiler_rt_runtime(clang_rt.ubsan-${arch} ${arch} STATIC
- SOURCES ${UBSAN_SOURCES}
+ SOURCES $<TARGET_OBJECTS:RTUbsan.${arch}>
CFLAGS ${UBSAN_CFLAGS})
- # C++-specific parts of UBSan runtime. Requires a C++ ABI library.
add_compiler_rt_runtime(clang_rt.ubsan_cxx-${arch} ${arch} STATIC
- SOURCES ${UBSAN_CXX_SOURCES}
+ SOURCES $<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
CFLAGS ${UBSAN_CXXFLAGS})
+
add_dependencies(ubsan
- clang_rt.san-${arch}
clang_rt.ubsan-${arch}
- clang_rt.ubsan_cxx-${arch})
+ clang_rt.ubsan_cxx-${arch}
+ clang_rt.ubsan_standalone-${arch}
+ clang_rt.ubsan_standalone_cxx-${arch})
if (UNIX AND NOT ${arch} MATCHES "i386|i686")
add_sanitizer_rt_symbols(clang_rt.ubsan-${arch} ubsan.syms.extra)
add_sanitizer_rt_symbols(clang_rt.ubsan_cxx-${arch} ubsan.syms.extra)
+ add_sanitizer_rt_symbols(clang_rt.ubsan_standalone-${arch} ubsan.syms.extra)
+ add_sanitizer_rt_symbols(clang_rt.ubsan_standalone_cxx-${arch} ubsan.syms.extra)
add_dependencies(ubsan
clang_rt.ubsan-${arch}-symbols
- clang_rt.ubsan_cxx-${arch}-symbols)
+ clang_rt.ubsan_cxx-${arch}-symbols
+ clang_rt.ubsan_standalone-${arch}-symbols
+ clang_rt.ubsan_standalone_cxx-${arch}-symbols)
endif()
endforeach()
endif()
diff --git a/lib/ubsan/ubsan_diag.cc b/lib/ubsan/ubsan_diag.cc
index 4f2a2a9f3..2314fb6ed 100644
--- a/lib/ubsan/ubsan_diag.cc
+++ b/lib/ubsan/ubsan_diag.cc
@@ -11,6 +11,8 @@
//
//===----------------------------------------------------------------------===//
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
#include "ubsan_diag.h"
#include "ubsan_init.h"
#include "ubsan_flags.h"
@@ -49,8 +51,13 @@ static void MaybeReportErrorSummary(Location Loc) {
if (Loc.isSourceLocation()) {
SourceLocation SLoc = Loc.getSourceLocation();
if (!SLoc.isInvalid()) {
- ReportErrorSummary("undefined-behavior", SLoc.getFilename(),
- SLoc.getLine(), "");
+ AddressInfo AI;
+ AI.file = internal_strdup(SLoc.getFilename());
+ AI.line = SLoc.getLine();
+ AI.column = SLoc.getColumn();
+ AI.function = internal_strdup(""); // Avoid printing ?? as function name.
+ ReportErrorSummary("undefined-behavior", AI);
+ AI.Clear();
return;
}
}
@@ -356,3 +363,5 @@ bool __ubsan::IsVptrCheckSuppressed(const char *TypeName) {
Suppression *s;
return suppression_ctx->Match(TypeName, kVptrCheck, &s);
}
+
+#endif // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_flags.cc b/lib/ubsan/ubsan_flags.cc
index 0dbffc9b1..49ada8a26 100644
--- a/lib/ubsan/ubsan_flags.cc
+++ b/lib/ubsan/ubsan_flags.cc
@@ -11,6 +11,8 @@
//
//===----------------------------------------------------------------------===//
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
#include "ubsan_flags.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flags.h"
@@ -77,3 +79,5 @@ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
const char *__ubsan_default_options() { return ""; }
} // extern "C"
#endif
+
+#endif // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc
index 78e7508f7..a65b2f5e3 100644
--- a/lib/ubsan/ubsan_handlers.cc
+++ b/lib/ubsan/ubsan_handlers.cc
@@ -11,6 +11,8 @@
//
//===----------------------------------------------------------------------===//
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
#include "ubsan_handlers.h"
#include "ubsan_diag.h"
@@ -419,3 +421,5 @@ void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) {
handleNonNullArg(Data, Opts);
Die();
}
+
+#endif // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_handlers_cxx.cc b/lib/ubsan/ubsan_handlers_cxx.cc
index 4718e6eac..b3cda32a9 100644
--- a/lib/ubsan/ubsan_handlers_cxx.cc
+++ b/lib/ubsan/ubsan_handlers_cxx.cc
@@ -13,6 +13,8 @@
//
//===----------------------------------------------------------------------===//
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
#include "ubsan_handlers_cxx.h"
#include "ubsan_diag.h"
#include "ubsan_type_hash.h"
@@ -79,3 +81,5 @@ void __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort(
GET_REPORT_OPTIONS(true);
HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts);
}
+
+#endif // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_init.cc b/lib/ubsan/ubsan_init.cc
index 219273d51..952726977 100644
--- a/lib/ubsan/ubsan_init.cc
+++ b/lib/ubsan/ubsan_init.cc
@@ -11,6 +11,8 @@
//
//===----------------------------------------------------------------------===//
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
#include "ubsan_diag.h"
#include "ubsan_init.h"
#include "ubsan_flags.h"
@@ -61,3 +63,5 @@ class UbsanInitializer {
};
static UbsanInitializer ubsan_initializer;
#endif // SANITIZER_CAN_USE_PREINIT_ARRAY
+
+#endif // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_platform.h b/lib/ubsan/ubsan_platform.h
new file mode 100644
index 000000000..efb7974d4
--- /dev/null
+++ b/lib/ubsan/ubsan_platform.h
@@ -0,0 +1,26 @@
+//===-- ubsan_platform.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the platforms which UBSan is supported at.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_PLATFORM_H
+#define UBSAN_PLATFORM_H
+
+// Other platforms should be easy to add, and probably work as-is.
+#if (defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)) && \
+ (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || \
+ defined(__aarch64__) || defined(__mips__))
+# define CAN_SANITIZE_UB 1
+#else
+# define CAN_SANITIZE_UB 0
+# error "UBSan not supported for this platform!"
+#endif
+
+#endif
diff --git a/lib/ubsan/ubsan_type_hash.cc b/lib/ubsan/ubsan_type_hash.cc
index a388bcc6d..c85d68dfd 100644
--- a/lib/ubsan/ubsan_type_hash.cc
+++ b/lib/ubsan/ubsan_type_hash.cc
@@ -13,6 +13,8 @@
//
//===----------------------------------------------------------------------===//
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
#include "ubsan_type_hash.h"
#include "sanitizer_common/sanitizer_common.h"
@@ -248,3 +250,5 @@ __ubsan::DynamicTypeInfo __ubsan::getDynamicTypeInfo(void *Object) {
return DynamicTypeInfo(Vtable->TypeInfo->__type_name, -Vtable->Offset,
ObjectType ? ObjectType->__type_name : "<unknown>");
}
+
+#endif // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_value.cc b/lib/ubsan/ubsan_value.cc
index ab74720f6..ea91d63bb 100644
--- a/lib/ubsan/ubsan_value.cc
+++ b/lib/ubsan/ubsan_value.cc
@@ -12,6 +12,8 @@
//
//===----------------------------------------------------------------------===//
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
#include "ubsan_value.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
@@ -100,3 +102,5 @@ FloatMax Value::getFloatValue() const {
}
UNREACHABLE("unexpected floating point bit width");
}
+
+#endif // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_value.h b/lib/ubsan/ubsan_value.h
index a68108440..72eee1555 100644
--- a/lib/ubsan/ubsan_value.h
+++ b/lib/ubsan/ubsan_value.h
@@ -14,12 +14,6 @@
#ifndef UBSAN_VALUE_H
#define UBSAN_VALUE_H
-// For now, only support Linux, FreeBSD and Darwin. Other platforms should
-// be easy to add, and probably work as-is.
-#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__APPLE__)
-#error "UBSan not supported for this platform!"
-#endif
-
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_common.h"
@@ -32,7 +26,6 @@ __extension__ typedef unsigned __int128 u128;
#define HAVE_INT128_T 0
#endif
-
namespace __ubsan {
/// \brief Largest integer types we support.
diff --git a/make/platform/clang_darwin.mk b/make/platform/clang_darwin.mk
index 4f71c0b46..b0e88021e 100644
--- a/make/platform/clang_darwin.mk
+++ b/make/platform/clang_darwin.mk
@@ -119,8 +119,11 @@ UniversalArchs.asan_osx_dynamic := $(call CheckArches,i386 x86_64 x86_64h,asan_o
Configs += asan_iossim_dynamic
UniversalArchs.asan_iossim_dynamic := $(call CheckArches,i386 x86_64,asan_iossim_dynamic,$(IOSSIM_SDK))
-Configs += ubsan_osx
-UniversalArchs.ubsan_osx := $(call CheckArches,i386 x86_64 x86_64h,ubsan_osx,$(OSX_SDK))
+Configs += ubsan_osx_dynamic
+UniversalArchs.ubsan_osx_dynamic := $(call CheckArches,i386 x86_64 x86_64h,ubsan_osx_dynamic,$(OSX_SDK))
+
+Configs += ubsan_iossim_dynamic
+UniversalArchs.ubsan_iossim_dynamic := $(call CheckArches,i386 x86_64,ubsan_iossim_dynamic,$(IOSSIM_SDK))
# Darwin 10.6 has a bug in cctools that makes it unable to use ranlib on our ARM
# object files. If we are on that platform, strip out all ARM archs. We still
@@ -172,26 +175,31 @@ IOSSIM_DEPLOYMENT_ARGS += -isysroot $(IOSSIM_SDK)
CFLAGS.eprintf := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS)
CFLAGS.10.4 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS)
+SANITIZER_MACOSX_DEPLOYMENT_ARGS := -mmacosx-version-min=10.7
+SANITIZER_IOSSIM_DEPLOYMENT_ARGS := -mios-simulator-version-min=7.0 \
+ -isysroot $(IOSSIM_SDK)
+SANITIZER_CFLAGS := -fno-builtin -gline-tables-only -stdlib=libc++
+
CFLAGS.asan_osx_dynamic := \
- $(CFLAGS) -mmacosx-version-min=10.7 \
- -stdlib=libc++ \
- -isysroot $(OSX_SDK) \
- -fno-builtin \
- -gline-tables-only \
+ $(CFLAGS) $(SANITIZER_MACOSX_DEPLOYMENT_ARGS) \
+ $(SANITIZER_CFLAGS) \
-DMAC_INTERPOSE_FUNCTIONS=1 \
-DASAN_DYNAMIC=1
CFLAGS.asan_iossim_dynamic := \
- $(CFLAGS) -mios-simulator-version-min=7.0 \
- -isysroot $(IOSSIM_SDK) \
- -fno-builtin \
- -gline-tables-only \
+ $(CFLAGS) $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS) \
+ $(SANITIZER_CFLAGS) \
-DMAC_INTERPOSE_FUNCTIONS=1 \
-DASAN_DYNAMIC=1
-CFLAGS.ubsan_osx := $(CFLAGS) -mmacosx-version-min=10.6 \
- -isysroot $(OSX_SDK) \
- -fno-builtin
+CFLAGS.ubsan_osx_dynamic := \
+ $(CFLAGS) $(SANITIZER_MACOSX_DEPLOYMENT_ARGS) \
+ $(SANITIZER_CFLAGS)
+
+CFLAGS.ubsan_iossim_dynamic := \
+ $(CFLAGS) $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS) \
+ $(SANITIZER_CFLAGS)
+
CFLAGS.ios.i386 := $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS)
CFLAGS.ios.x86_64 := $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS)
@@ -222,19 +230,30 @@ CFLAGS.profile_ios.armv7k := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS)
CFLAGS.profile_ios.armv7s := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS)
CFLAGS.profile_ios.arm64 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS)
-# Configure the asan_osx_dynamic library to be built shared.
+SANITIZER_LDFLAGS := -stdlib=libc++ -lc++
+
SHARED_LIBRARY.asan_osx_dynamic := 1
-LDFLAGS.asan_osx_dynamic := -lc++ -undefined dynamic_lookup -install_name @rpath/libclang_rt.asan_osx_dynamic.dylib \
- -mmacosx-version-min=10.7 \
- -isysroot $(OSX_SDK)
+LDFLAGS.asan_osx_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.asan_osx_dynamic.dylib \
+ $(SANITIZER_MACOSX_DEPLOYMENT_ARGS)
-# Configure the asan_iossim_dynamic library to be built shared.
SHARED_LIBRARY.asan_iossim_dynamic := 1
-# configure+make uses Clang, so we're using isysroot instead of --sysroot
-# or -Wl,-syslibroot.
-LDFLAGS.asan_iossim_dynamic := -undefined dynamic_lookup -install_name @rpath/libclang_rt.asan_iossim_dynamic.dylib \
- -Wl,-ios_simulator_version_min,7.0.0 \
- -mios-simulator-version-min=7.0 -isysroot $(IOSSIM_SDK)
+LDFLAGS.asan_iossim_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.asan_iossim_dynamic.dylib \
+ -Wl,-ios_simulator_version_min,7.0.0 $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS)
+
+SHARED_LIBRARY.ubsan_osx_dynamic := 1
+LDFLAGS.ubsan_osx_dynamic := $(SANITIZER_LDFLAGS) -lc++abi -install_name @rpath/libclang_rt.ubsan_osx_dynamic.dylib \
+ $(SANITIZER_MACOSX_DEPLOYMENT_ARGS)
+
+SHARED_LIBRARY.ubsan_iossim_dynamic := 1
+LDFLAGS.ubsan_iossim_dynamic := $(SANITIZER_LDFLAGS) -lc++abi -install_name @rpath/libclang_rt.ubsan_iossim_dynamic.dylib \
+ -Wl,-ios_simulator_version_min,7.0.0 $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS)
+
+ifneq ($(OSX_SDK),)
+CFLAGS.asan_osx_dynamic += -isysroot $(OSX_SDK)
+LDFLAGS.asan_osx_dynamic += -isysroot $(OSX_SDK)
+CFLAGS.ubsan_osx_dynamic += -isysroot $(OSX_SDK)
+LDFLAGS.ubsan_osx_dynamic += -isysroot $(OSX_SDK)
+endif
FUNCTIONS.eprintf := eprintf
FUNCTIONS.10.4 := eprintf floatundidf floatundisf floatundixf
@@ -256,15 +275,18 @@ FUNCTIONS.profile_ios := $(FUNCTIONS.profile_osx)
FUNCTIONS.asan_osx_dynamic := $(AsanFunctions) $(AsanCXXFunctions) \
$(InterceptionFunctions) \
$(SanitizerCommonFunctions) \
- $(AsanDynamicFunctions)
+ $(AsanDynamicFunctions)
FUNCTIONS.asan_iossim_dynamic := $(AsanFunctions) $(AsanCXXFunctions) \
$(InterceptionFunctions) \
$(SanitizerCommonFunctions) \
- $(AsanDynamicFunctions)
+ $(AsanDynamicFunctions)
+
+FUNCTIONS.ubsan_osx_dynamic := $(UbsanFunctions) $(UbsanCXXFunctions) \
+ $(SanitizerCommonFunctions)
-FUNCTIONS.ubsan_osx := $(UbsanFunctions) $(UbsanCXXFunctions) \
- $(SanitizerCommonFunctions)
+FUNCTIONS.ubsan_iossim_dynamic := $(UbsanFunctions) $(UbsanCXXFunctions) \
+ $(SanitizerCommonFunctions)
CCKEXT_PROFILE_FUNCTIONS := \
InstrProfiling \
diff --git a/make/platform/clang_linux.mk b/make/platform/clang_linux.mk
index cb023f3db..4585cd969 100644
--- a/make/platform/clang_linux.mk
+++ b/make/platform/clang_linux.mk
@@ -74,12 +74,6 @@ CFLAGS.builtins-x86_64 := $(CFLAGS) -m64
CFLAGS.profile-i386 := $(CFLAGS) -m32
CFLAGS.profile-x86_64 := $(CFLAGS) -m64
-# Use our stub SDK as the sysroot to support more portable building. For now we
-# just do this for the core module, because the stub SDK doesn't have
-# enough support to build the profile runtime.
-CFLAGS.builtins-i386 += --sysroot=$(ProjSrcRoot)/SDKs/linux
-CFLAGS.builtins-x86_64 += --sysroot=$(ProjSrcRoot)/SDKs/linux
-
FUNCTIONS.builtins-i386 := $(CommonFunctions) $(ArchFunctions.i386)
FUNCTIONS.builtins-x86_64 := $(CommonFunctions) $(ArchFunctions.x86_64)
FUNCTIONS.profile-i386 := GCDAProfiling InstrProfiling InstrProfilingBuffer \
diff --git a/test/asan/CMakeLists.txt b/test/asan/CMakeLists.txt
index e1b812646..08c168988 100644
--- a/test/asan/CMakeLists.txt
+++ b/test/asan/CMakeLists.txt
@@ -5,9 +5,9 @@ set(ASAN_DYNAMIC_TESTSUITES)
macro(get_bits_for_arch arch bits)
if (${arch} MATCHES "i386|i686|arm|mips|mipsel")
- set(bits 32)
+ set(${bits} 32)
elseif (${arch} MATCHES "x86_64|powerpc64|powerpc64le|aarch64|mips64|mips64el")
- set(bits 64)
+ set(${bits} 64)
else()
message(FATAL_ERROR "Unknown target architecture: ${arch}")
endif()
diff --git a/test/asan/TestCases/Darwin/atos-symbolizer.cc b/test/asan/TestCases/Darwin/atos-symbolizer.cc
new file mode 100644
index 000000000..a4df3a2e5
--- /dev/null
+++ b/test/asan/TestCases/Darwin/atos-symbolizer.cc
@@ -0,0 +1,28 @@
+// Check that the `atos` symbolizer works.
+
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: ASAN_OPTIONS=verbosity=2 ASAN_SYMBOLIZER_PATH=$(which atos) not %run %t 2>&1 | FileCheck %s
+
+// Check that when having a DYLD_ROOT_PATH set, the symbolizer still works.
+// RUN: DYLD_ROOT_PATH="/" ASAN_OPTIONS=verbosity=2 ASAN_SYMBOLIZER_PATH=$(which atos) \
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+#include <string.h>
+int main(int argc, char **argv) {
+ char *x = (char*)malloc(10 * sizeof(char));
+ memset(x, 0, 10);
+ int res = x[argc];
+ free(x);
+ free(x + argc - 1); // BOOM
+ // CHECK: AddressSanitizer: attempting double-free{{.*}}in thread T0
+ // CHECK: Using atos at user-specified path:
+ // CHECK: #0 0x{{.*}} in {{.*}}free
+ // CHECK: #1 0x{{.*}} in main {{.*}}atos-symbolizer.cc:[[@LINE-4]]
+ // CHECK: freed by thread T0 here:
+ // CHECK: #0 0x{{.*}} in {{.*}}free
+ // CHECK: #1 0x{{.*}} in main {{.*}}atos-symbolizer.cc:[[@LINE-8]]
+ // CHECK: allocated by thread T0 here:
+ // CHECK: atos-symbolizer.cc:[[@LINE-13]]
+ return res;
+}
diff --git a/test/asan/TestCases/Darwin/dladdr-demangling.cc b/test/asan/TestCases/Darwin/dladdr-demangling.cc
new file mode 100644
index 000000000..494007f51
--- /dev/null
+++ b/test/asan/TestCases/Darwin/dladdr-demangling.cc
@@ -0,0 +1,33 @@
+// In a non-forking sandbox, we fallback to dladdr(). Test that we provide
+// properly demangled C++ names in that case.
+
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=verbosity=2 not %run sandbox-exec -p '(version 1)(allow default)(deny process-fork)' %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DLADDR
+
+#include <stdlib.h>
+
+class MyClass {
+ public:
+ int my_function(int n) {
+ char *x = (char*)malloc(n * sizeof(char));
+ free(x);
+ return x[5];
+ // CHECK: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
+ // CHECK: {{READ of size 1 at 0x.* thread T0}}
+ // CHECK-DLADDR: Using dladdr symbolizer
+ // CHECK-DLADDR: failed to fork external symbolizer
+ // CHECK: {{ #0 0x.* in MyClass::my_function\(int\)}}
+ // CHECK: {{freed by thread T0 here:}}
+ // CHECK: {{ #0 0x.* in wrap_free}}
+ // CHECK: {{ #1 0x.* in MyClass::my_function\(int\)}}
+ // CHECK: {{previously allocated by thread T0 here:}}
+ // CHECK: {{ #0 0x.* in wrap_malloc}}
+ // CHECK: {{ #1 0x.* in MyClass::my_function\(int\)}}
+ }
+};
+
+int main() {
+ MyClass o;
+ return o.my_function(10);
+}
diff --git a/test/asan/TestCases/Darwin/interface_symbols_darwin.c b/test/asan/TestCases/Darwin/interface_symbols_darwin.c
index a75044d49..bd9bbee84 100644
--- a/test/asan/TestCases/Darwin/interface_symbols_darwin.c
+++ b/test/asan/TestCases/Darwin/interface_symbols_darwin.c
@@ -29,6 +29,18 @@
// RUN: echo __asan_report_store16 >> %t.interface
// RUN: echo __asan_report_load_n >> %t.interface
// RUN: echo __asan_report_store_n >> %t.interface
+// RUN: echo __asan_report_exp_load1 >> %t.interface
+// RUN: echo __asan_report_exp_load2 >> %t.interface
+// RUN: echo __asan_report_exp_load4 >> %t.interface
+// RUN: echo __asan_report_exp_load8 >> %t.interface
+// RUN: echo __asan_report_exp_load16 >> %t.interface
+// RUN: echo __asan_report_exp_store1 >> %t.interface
+// RUN: echo __asan_report_exp_store2 >> %t.interface
+// RUN: echo __asan_report_exp_store4 >> %t.interface
+// RUN: echo __asan_report_exp_store8 >> %t.interface
+// RUN: echo __asan_report_exp_store16 >> %t.interface
+// RUN: echo __asan_report_exp_load_n >> %t.interface
+// RUN: echo __asan_report_exp_store_n >> %t.interface
// RUN: echo __asan_get_current_fake_stack >> %t.interface
// RUN: echo __asan_addr_is_in_fake_stack >> %t.interface
// RUN: echo __asan_mz_calloc >> %t.interface
diff --git a/test/asan/TestCases/Darwin/sandbox-symbolizer.cc b/test/asan/TestCases/Darwin/sandbox-symbolizer.cc
new file mode 100644
index 000000000..431337187
--- /dev/null
+++ b/test/asan/TestCases/Darwin/sandbox-symbolizer.cc
@@ -0,0 +1,29 @@
+// In a non-forking sandbox, we can't spawn an external symbolizer, but dladdr()
+// should still work and provide function names. No line numbers though.
+// Second, `atos` symbolizer can't inspect a process that has an inaccessible
+// task port, in which case we should again fallback to dladdr gracefully.
+
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %run sandbox-exec -p '(version 1)(allow default)(deny process-fork)' %t 2>&1 | FileCheck %s
+// RUN: not %run sandbox-exec -p '(version 1)(allow default)(deny mach-priv-task-port)' %t 2>&1 | FileCheck %s
+// RUN: ASAN_SYMBOLIZER_PATH="" not %run sandbox-exec -p '(version 1)(allow default)(deny mach-priv-task-port)' %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t
+// RUN: not %run sandbox-exec -p '(version 1)(allow default)(deny process-fork)' %t 2>&1 | FileCheck %s
+// RUN: not %run sandbox-exec -p '(version 1)(allow default)(deny mach-priv-task-port)' %t 2>&1 | FileCheck %s
+// RUN: ASAN_SYMBOLIZER_PATH="" not %run sandbox-exec -p '(version 1)(allow default)(deny mach-priv-task-port)' %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+ // CHECK: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
+ // CHECK: {{READ of size 1 at 0x.* thread T0}}
+ // CHECK: {{ #0 0x.* in main}}
+ // CHECK: {{freed by thread T0 here:}}
+ // CHECK: {{ #0 0x.* in wrap_free}}
+ // CHECK: {{ #1 0x.* in main}}
+ // CHECK: {{previously allocated by thread T0 here:}}
+ // CHECK: {{ #0 0x.* in wrap_malloc}}
+ // CHECK: {{ #1 0x.* in main}}
+}
diff --git a/test/asan/TestCases/Darwin/suppressions-sandbox.cc b/test/asan/TestCases/Darwin/suppressions-sandbox.cc
new file mode 100644
index 000000000..59fe47510
--- /dev/null
+++ b/test/asan/TestCases/Darwin/suppressions-sandbox.cc
@@ -0,0 +1,26 @@
+// Check that without suppressions, we catch the issue.
+// RUN: %clangxx_asan -O0 %s -o %t -framework Foundation
+// RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
+
+// Check that suppressing a function name works within a no-fork sandbox
+// RUN: echo "interceptor_via_fun:CFStringCreateWithBytes" > %t.supp
+// RUN: ASAN_OPTIONS=suppressions=%t.supp \
+// RUN: sandbox-exec -p '(version 1)(allow default)(deny process-fork)' \
+// RUN: %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
+
+#include <CoreFoundation/CoreFoundation.h>
+
+int main() {
+ char *a = (char *)malloc(6);
+ strcpy(a, "hello");
+ CFStringRef str =
+ CFStringCreateWithBytes(kCFAllocatorDefault, (unsigned char *)a, 10,
+ kCFStringEncodingUTF8, FALSE); // BOOM
+ fprintf(stderr, "Ignored.\n");
+ free(a);
+}
+
+// CHECK-CRASH: AddressSanitizer: heap-buffer-overflow
+// CHECK-CRASH-NOT: Ignored.
+// CHECK-IGNORE-NOT: AddressSanitizer: heap-buffer-overflow
+// CHECK-IGNORE: Ignored.
diff --git a/test/asan/TestCases/Linux/coverage-module-unloaded.cc b/test/asan/TestCases/Linux/coverage-module-unloaded.cc
index f8d9c57f8..573fc4664 100644
--- a/test/asan/TestCases/Linux/coverage-module-unloaded.cc
+++ b/test/asan/TestCases/Linux/coverage-module-unloaded.cc
@@ -50,7 +50,7 @@ int main(int argc, char **argv) {
// CHECK: PID: [[PID:[0-9]+]]
// CHECK: [[PID]].sancov: 1 PCs written
-// CHECK: .so.[[PID]]
-// If we get coverage for both DSOs, it means the module wasn't unloaded and
-// this test is useless.
-// CHECK-NOT: .so.[[PID]]
+// CHECK: test_1.so.[[PID]]
+// CHECK: test_2.so.[[PID]]
+// Even though we've unloaded one of the libs we still dump the coverage file
+// for that lib (although the data will be inaccurate, it at all useful)
diff --git a/test/asan/TestCases/Linux/coverage-sandboxing.cc b/test/asan/TestCases/Linux/coverage-sandboxing.cc
index 1a72c6bb9..15bada886 100644
--- a/test/asan/TestCases/Linux/coverage-sandboxing.cc
+++ b/test/asan/TestCases/Linux/coverage-sandboxing.cc
@@ -78,8 +78,8 @@ int main(int argc, char **argv) {
#endif
// CHECK-vanilla: PID: [[PID:[0-9]+]]
-// CHECK-vanilla: [[PID]].sancov: 1 PCs written
// CHECK-vanilla: .so.[[PID]].sancov: 258 PCs written
+// CHECK-vanilla: [[PID]].sancov: 1 PCs written
// CHECK-sandbox: PID: [[PID:[0-9]+]]
// CHECK-sandbox: 258 PCs written to packed file
diff --git a/test/asan/TestCases/Linux/coverage.cc b/test/asan/TestCases/Linux/coverage.cc
index 06fe1a295..1ad19e66c 100644
--- a/test/asan/TestCases/Linux/coverage.cc
+++ b/test/asan/TestCases/Linux/coverage.cc
@@ -1,11 +1,18 @@
// RUN: %clangxx_asan -fsanitize-coverage=1 -DSHARED %s -shared -o %T/libcoverage_test.so -fPIC
// RUN: %clangxx_asan -fsanitize-coverage=1 %s -o %t -Wl,-R,\$ORIGIN -L%T -lcoverage_test
// RUN: export ASAN_OPTIONS=coverage=1:verbosity=1
-// RUN: mkdir -p %T/coverage && cd %T/coverage
+// RUN: rm -rf %T/coverage && mkdir -p %T/coverage && cd %T/coverage
// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-main
+// RUN: %sancov print coverage.*sancov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV1
// RUN: %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-foo
+// RUN: %sancov print coverage.*sancov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV2
// RUN: %run %t bar 2>&1 | FileCheck %s --check-prefix=CHECK-bar
+// RUN: %sancov print coverage.*sancov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV2
// RUN: %run %t foo bar 2>&1 | FileCheck %s --check-prefix=CHECK-foo-bar
+// RUN: %sancov print coverage.*sancov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV2
+// RUN: %sancov print libcoverage_test.*sancov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV1
+// RUN: %sancov merge coverage.*sancov > merged-cov
+// RUN: %sancov print merged-cov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV2
// RUN: not %run %t foo bar 4 2>&1 | FileCheck %s --check-prefix=CHECK-report
// RUN: not %run %t foo bar 4 5 2>&1 | FileCheck %s --check-prefix=CHECK-segv
// RUN: cd .. && rm coverage -r
@@ -57,15 +64,18 @@ int main(int argc, char **argv) {
// CHECK-foo-NOT: .so.[[PID]]
//
// CHECK-bar: PID: [[PID:[0-9]+]]
-// CHECK-bar: [[PID]].sancov: 1 PCs written
// CHECK-bar: .so.[[PID]].sancov: 1 PCs written
+// CHECK-bar: [[PID]].sancov: 1 PCs written
//
// CHECK-foo-bar: PID: [[PID:[0-9]+]]
-// CHECK-foo-bar: [[PID]].sancov: 2 PCs written
// CHECK-foo-bar: so.[[PID]].sancov: 1 PCs written
+// CHECK-foo-bar: [[PID]].sancov: 2 PCs written
//
// CHECK-report: AddressSanitizer: global-buffer-overflow
// CHECK-report: PCs written
//
// CHECK-segv: AddressSanitizer: SEGV
// CHECK-segv: PCs written
+//
+// CHECK-SANCOV1: 1 PCs total
+// CHECK-SANCOV2: 2 PCs total
diff --git a/test/asan/TestCases/Linux/interface_symbols_linux.c b/test/asan/TestCases/Linux/interface_symbols_linux.c
index a616732ff..bec501b84 100644
--- a/test/asan/TestCases/Linux/interface_symbols_linux.c
+++ b/test/asan/TestCases/Linux/interface_symbols_linux.c
@@ -24,6 +24,18 @@
// RUN: echo __asan_report_store16 >> %t.interface
// RUN: echo __asan_report_load_n >> %t.interface
// RUN: echo __asan_report_store_n >> %t.interface
+// RUN: echo __asan_report_exp_load1 >> %t.interface
+// RUN: echo __asan_report_exp_load2 >> %t.interface
+// RUN: echo __asan_report_exp_load4 >> %t.interface
+// RUN: echo __asan_report_exp_load8 >> %t.interface
+// RUN: echo __asan_report_exp_load16 >> %t.interface
+// RUN: echo __asan_report_exp_store1 >> %t.interface
+// RUN: echo __asan_report_exp_store2 >> %t.interface
+// RUN: echo __asan_report_exp_store4 >> %t.interface
+// RUN: echo __asan_report_exp_store8 >> %t.interface
+// RUN: echo __asan_report_exp_store16 >> %t.interface
+// RUN: echo __asan_report_exp_load_n >> %t.interface
+// RUN: echo __asan_report_exp_store_n >> %t.interface
// RUN: echo __asan_get_current_fake_stack >> %t.interface
// RUN: echo __asan_addr_is_in_fake_stack >> %t.interface
// RUN: cat %t.interface | sort -u | diff %t.symbols -
diff --git a/test/asan/TestCases/Linux/leak_check_segv.cc b/test/asan/TestCases/Linux/leak_check_segv.cc
new file mode 100644
index 000000000..8160d5fe5
--- /dev/null
+++ b/test/asan/TestCases/Linux/leak_check_segv.cc
@@ -0,0 +1,23 @@
+// Test that SIGSEGV during leak checking does not crash the process.
+// RUN: %clangxx_asan -O1 %s -o %t && LSAN_OPTIONS="verbosity=1" not %run %t 2>&1
+// REQUIRES: leak-detection
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sanitizer/lsan_interface.h>
+
+char data[10 * 1024 * 1024];
+
+int main() {
+ void *p = malloc(10 * 1024 * 1024);
+ // surprise-surprise!
+ mprotect((void*)(((unsigned long)p + 4095) & ~4095), 16 * 1024, PROT_NONE);
+ mprotect((void*)(((unsigned long)data + 4095) & ~4095), 16 * 1024, PROT_NONE);
+ __lsan_do_leak_check();
+ fprintf(stderr, "DONE\n");
+}
+
+// CHECK: Tracer caught signal 11
+// CHECK: LeakSanitizer has encountered a fatal error
+// CHECK-NOT: DONE
+
diff --git a/test/asan/TestCases/Linux/nohugepage_test.cc b/test/asan/TestCases/Linux/nohugepage_test.cc
index b549f3bc2..337b95dc0 100644
--- a/test/asan/TestCases/Linux/nohugepage_test.cc
+++ b/test/asan/TestCases/Linux/nohugepage_test.cc
@@ -22,15 +22,31 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
+#include <errno.h>
#include <sanitizer/asan_interface.h>
-char FileContents[1 << 14];
+char FileContents[1 << 16];
void FileToString(const char *path) {
FileContents[0] = 0;
int fd = open(path, 0);
if (fd < 0) return;
- ssize_t res = read(fd, FileContents, sizeof(FileContents) - 1);
+ char *p = FileContents;
+ ssize_t size = sizeof(FileContents) - 1;
+ ssize_t res = 0;
+ do {
+ ssize_t got = read (fd, p, size);
+ if (got == 0)
+ break;
+ else if (got > 0)
+ {
+ p += got;
+ res += got;
+ size -= got;
+ }
+ else if (errno != EINTR)
+ break;
+ } while (size > 0 && res < sizeof(FileContents));
if (res >= 0)
FileContents[res] = 0;
}
diff --git a/test/asan/TestCases/Linux/ptrace.cc b/test/asan/TestCases/Linux/ptrace.cc
index 7e5acb64c..6840ebe28 100644
--- a/test/asan/TestCases/Linux/ptrace.cc
+++ b/test/asan/TestCases/Linux/ptrace.cc
@@ -31,8 +31,8 @@ int main(void) {
// CHECK: AddressSanitizer: stack-buffer-overflow
// CHECK: {{.*ptrace.cc:}}[[@LINE-2]]
assert(!res);
-#if __WORDSIZE == 64
- printf("%zx\n", regs.rip);
+#ifdef __x86_64__
+ printf("%lx\n", (unsigned long)regs.rip);
#else
printf("%lx\n", regs.eip);
#endif
@@ -42,7 +42,7 @@ int main(void) {
assert(!res);
printf("%lx\n", (unsigned long)fpregs.cwd);
-#if __WORDSIZE == 32
+#ifndef __x86_64__
user_fpxregs_struct fpxregs;
res = ptrace(PTRACE_GETFPXREGS, pid, NULL, &fpxregs);
assert(!res);
diff --git a/test/asan/TestCases/Linux/signal_during_stop_the_world.cc b/test/asan/TestCases/Linux/signal_during_stop_the_world.cc
new file mode 100644
index 000000000..b1a41fe20
--- /dev/null
+++ b/test/asan/TestCases/Linux/signal_during_stop_the_world.cc
@@ -0,0 +1,60 @@
+// Test StopTheWorld behavior during signal storm.
+// Historically StopTheWorld crashed because did not handle EINTR properly.
+// The test is somewhat convoluted, but that's what caused crashes previously.
+
+// RUN: %clangxx_asan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/prctl.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <pthread.h>
+#include <sanitizer/lsan_interface.h>
+
+static void handler(int signo);
+static void *thr(void *arg);
+
+int main() {
+ struct sigaction act = {};
+ act.sa_handler = handler;
+ sigaction(SIGPROF, &act, 0);
+
+ pid_t pid = fork();
+ if (pid < 0) {
+ fprintf(stderr, "failed to fork\n");
+ exit(1);
+ }
+ if (pid == 0) {
+ // Child constantly sends signals to parent to cause spurious return from
+ // waitpid in StopTheWorld.
+ prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
+ pid_t parent = getppid();
+ for (;;) {
+ // There is no strong reason for these two particular signals,
+ // but at least one of them ought to unblock waitpid.
+ kill(parent, SIGCHLD);
+ kill(parent, SIGPROF);
+ }
+ }
+ usleep(10000); // Let the child start.
+ __lsan_do_leak_check();
+ // Kill and join the child.
+ kill(pid, SIGTERM);
+ waitpid(pid, 0, 0);
+ sleep(1); // If the tracer thread still runs, give it time to crash.
+ fprintf(stderr, "DONE\n");
+// CHECK: DONE
+}
+
+static void handler(int signo) {
+}
+
+static void *thr(void *arg) {
+ for (;;)
+ sleep(1);
+ return 0;
+}
diff --git a/test/asan/TestCases/Linux/sized_delete_test.cc b/test/asan/TestCases/Linux/sized_delete_test.cc
index 1ce610f1b..140164464 100644
--- a/test/asan/TestCases/Linux/sized_delete_test.cc
+++ b/test/asan/TestCases/Linux/sized_delete_test.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_asan -Xclang -fdefine-sized-deallocation -Xclang -fsized-deallocation -O0 %s -o %t
+// RUN: %clangxx_asan -fsized-deallocation -O0 %s -o %t
// RUN: not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR
// RUN: ASAN_OPTIONS=new_delete_type_mismatch=1 not %run %t scalar 2>&1 | FileCheck %s -check-prefix=SCALAR
// RUN: not %run %t array 2>&1 | FileCheck %s -check-prefix=ARRAY
@@ -6,9 +6,10 @@
// RUN: ASAN_OPTIONS=new_delete_type_mismatch=0 %run %t scalar
// RUN: ASAN_OPTIONS=new_delete_type_mismatch=0 %run %t array
+// FIXME: the following two lines are not true after r232788.
// Sized-delete is implemented with a weak delete() definition.
// Weak symbols are kind of broken on Android.
-// XFAIL: android, asan-dynamic-runtime
+// XFAIL: android
#include <new>
#include <stdio.h>
diff --git a/test/asan/TestCases/Linux/coverage-direct.cc b/test/asan/TestCases/Posix/coverage-direct.cc
index 45222fa1a..45222fa1a 100644
--- a/test/asan/TestCases/Linux/coverage-direct.cc
+++ b/test/asan/TestCases/Posix/coverage-direct.cc
diff --git a/test/asan/TestCases/Linux/coverage-fork.cc b/test/asan/TestCases/Posix/coverage-fork.cc
index 38c200942..38c200942 100644
--- a/test/asan/TestCases/Linux/coverage-fork.cc
+++ b/test/asan/TestCases/Posix/coverage-fork.cc
diff --git a/test/asan/TestCases/log_path_fork_test.cc.disabled b/test/asan/TestCases/Posix/log_path_fork_test.cc.disabled
index cfe90dfb5..cfe90dfb5 100644
--- a/test/asan/TestCases/log_path_fork_test.cc.disabled
+++ b/test/asan/TestCases/Posix/log_path_fork_test.cc.disabled
diff --git a/test/asan/TestCases/Posix/start-deactivated.cc b/test/asan/TestCases/Posix/start-deactivated.cc
index d7e0dfc98..2eb02dff6 100644
--- a/test/asan/TestCases/Posix/start-deactivated.cc
+++ b/test/asan/TestCases/Posix/start-deactivated.cc
@@ -19,7 +19,6 @@
// RUN: ASAN_ACTIVATION_OPTIONS=help=1,handle_segv=0,verbosity=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-UNSUPPORTED
// XFAIL: arm-linux-gnueabi
-// XFAIL: armv7l-unknown-linux-gnueabihf
#if !defined(SHARED_LIB)
#include <assert.h>
diff --git a/test/asan/TestCases/Windows/bind_io_completion_callback.cc b/test/asan/TestCases/Windows/bind_io_completion_callback.cc
new file mode 100644
index 000000000..c062a799f
--- /dev/null
+++ b/test/asan/TestCases/Windows/bind_io_completion_callback.cc
@@ -0,0 +1,70 @@
+// 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: cl -c %s -Fo%t.obj
+// RUN: %clangxx_asan -o %t.exe %s %t.obj
+// RUN: %run %t.exe 2>&1 | FileCheck %s
+
+#include <windows.h>
+#include <stdio.h>
+
+void ThrowAndCatch();
+
+#if !defined(__clang__)
+__declspec(noinline)
+void Throw() {
+ fprintf(stderr, "Throw\n");
+// CHECK: Throw
+ throw 1;
+}
+
+void ThrowAndCatch() {
+ int local;
+ try {
+ Throw();
+ } catch(...) {
+ fprintf(stderr, "Catch\n");
+// CHECK: Catch
+ }
+}
+#else
+
+char buffer[65536];
+HANDLE done;
+OVERLAPPED ov;
+
+void CALLBACK completion_callback(DWORD error, DWORD bytesRead,
+ LPOVERLAPPED pov) {
+ ThrowAndCatch();
+ SetEvent(done);
+}
+
+int main(int argc, char **argv) {
+ done = CreateEvent(0, false, false, "job is done");
+ if (!done)
+ return 1;
+ HANDLE file = CreateFile(
+ argv[0], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED,
+ NULL);
+ if (!file)
+ return 2;
+ if (!BindIoCompletionCallback(file, completion_callback, 0))
+ return 3;
+
+ if (!ReadFile(file, buffer, sizeof(buffer), NULL, &ov) &&
+ GetLastError() != ERROR_IO_PENDING)
+ return 4;
+
+ if (WAIT_OBJECT_0 != WaitForSingleObject(done, INFINITE))
+ return 5;
+ fprintf(stderr, "Done!\n");
+// CHECK: Done!
+}
+#endif
diff --git a/test/asan/TestCases/Windows/dll_noreturn.cc b/test/asan/TestCases/Windows/dll_noreturn.cc
index 6ec907251..79f923ecc 100644
--- a/test/asan/TestCases/Windows/dll_noreturn.cc
+++ b/test/asan/TestCases/Windows/dll_noreturn.cc
@@ -9,7 +9,7 @@ void noreturn_f() {
char buffer[42];
buffer[subscript] = 42;
_exit(1);
-// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: AddressSanitizer: stack-buffer-underflow on address [[ADDR:0x[0-9a-f]+]]
// CHECK: WRITE of size 1 at [[ADDR]] thread T0
// CHECK-NEXT: noreturn_f {{.*}}dll_noreturn.cc:[[@LINE-4]]
// CHECK-NEXT: test_function {{.*}}dll_noreturn.cc
diff --git a/test/asan/TestCases/Windows/dll_report_globals_symbolization_at_startup.cc b/test/asan/TestCases/Windows/dll_report_globals_symbolization_at_startup.cc
new file mode 100644
index 000000000..fbdb1c145
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_report_globals_symbolization_at_startup.cc
@@ -0,0 +1,40 @@
+// RUN: %clang_cl_asan -LD -O0 -DDLL %s -Fe%t.dll
+// RUN: %clang_cl_asan -O0 -DEXE %s %t.lib -Fe%te.exe
+// RUN: env ASAN_OPTIONS=report_globals=2 %run %te.exe 2>&1 | FileCheck %s
+
+// FIXME: Currently, the MT runtime build crashes on startup due to dbghelp.dll
+// initialization failure.
+// REQUIRES: asan-dynamic-runtime
+
+#include <windows.h>
+#include <stdio.h>
+
+extern "C" {
+#if defined(EXE)
+__declspec(dllimport) int foo_from_dll();
+
+// CHECK: in DLL(reason=1)
+int main(int argc, char **argv) {
+ foo_from_dll();
+// CHECK: hello!
+ printf("hello!\n");
+ fflush(0);
+// CHECK: in DLL(reason=0)
+}
+#elif defined(DLL)
+// This global is registered at startup.
+int x[42];
+
+__declspec(dllexport) int foo_from_dll() {
+ return x[2];
+}
+
+BOOL WINAPI DllMain(HMODULE, DWORD reason, LPVOID) {
+ printf("in DLL(reason=%d)\n", (int)reason);
+ fflush(0);
+ return TRUE;
+}
+#else
+# error oops!
+#endif
+}
diff --git a/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc b/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc
index 8f5362341..04d3e2ec5 100644
--- a/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc
+++ b/test/asan/TestCases/Windows/dll_thread_stack_array_left_oob.cc
@@ -9,7 +9,7 @@ DWORD WINAPI thread_proc(void *context) {
int subscript = -1;
char stack_buffer[42];
stack_buffer[subscript] = 42;
-// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: AddressSanitizer: stack-buffer-underflow on address [[ADDR:0x[0-9a-f]+]]
// CHECK: WRITE of size 1 at [[ADDR]] thread T1
// CHECK-NEXT: thread_proc {{.*}}dll_thread_stack_array_left_oob.cc:[[@LINE-3]]
//
diff --git a/test/asan/TestCases/Windows/queue_user_work_item.cc b/test/asan/TestCases/Windows/queue_user_work_item.cc
new file mode 100644
index 000000000..d99ea6fc2
--- /dev/null
+++ b/test/asan/TestCases/Windows/queue_user_work_item.cc
@@ -0,0 +1,55 @@
+// 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: cl -c %s -Fo%t.obj
+// RUN: %clangxx_asan -o %t.exe %s %t.obj
+// RUN: %run %t.exe 2>&1 | FileCheck %s
+
+#include <windows.h>
+#include <stdio.h>
+
+void ThrowAndCatch();
+
+#if !defined(__clang__)
+__declspec(noinline)
+void Throw() {
+ fprintf(stderr, "Throw\n");
+// CHECK: Throw
+ throw 1;
+}
+
+void ThrowAndCatch() {
+ int local;
+ try {
+ Throw();
+ } catch(...) {
+ fprintf(stderr, "Catch\n");
+// CHECK: Catch
+ }
+}
+#else
+
+HANDLE done;
+
+DWORD CALLBACK work_item(LPVOID) {
+ ThrowAndCatch();
+ SetEvent(done);
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ done = CreateEvent(0, false, false, "job is done");
+ if (!done)
+ return 1;
+ QueueUserWorkItem(&work_item, nullptr, 0);
+ if (WAIT_OBJECT_0 != WaitForSingleObject(done, INFINITE))
+ return 2;
+ fprintf(stderr, "Done!\n");
+// CHECK: Done!
+}
+#endif
diff --git a/test/asan/TestCases/Windows/queue_user_work_item_report.cc b/test/asan/TestCases/Windows/queue_user_work_item_report.cc
new file mode 100644
index 000000000..a57e1e767
--- /dev/null
+++ b/test/asan/TestCases/Windows/queue_user_work_item_report.cc
@@ -0,0 +1,29 @@
+// RUN: %clang_cl_asan -O0 %s -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <windows.h>
+
+HANDLE done;
+
+DWORD CALLBACK work_item(LPVOID) {
+ int subscript = -1;
+ volatile char stack_buffer[42];
+ stack_buffer[subscript] = 42;
+// 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;
+}
+
+int main(int argc, char **argv) {
+ done = CreateEvent(0, false, false, "job is done");
+ if (!done)
+ return 1;
+// CHECK-NOT: Thread T1 created
+ QueueUserWorkItem(&work_item, nullptr, 0);
+ if (WAIT_OBJECT_0 != WaitForSingleObject(done, INFINITE))
+ return 2;
+}
diff --git a/test/asan/TestCases/Windows/report_globals_reload_dll.cc b/test/asan/TestCases/Windows/report_globals_reload_dll.cc
new file mode 100644
index 000000000..8b050975a
--- /dev/null
+++ b/test/asan/TestCases/Windows/report_globals_reload_dll.cc
@@ -0,0 +1,51 @@
+// Make sure we can handle reloading the same DLL multiple times.
+// RUN: %clang_cl_asan -LD -O0 -DDLL %s -Fe%t.dll
+// RUN: %clang_cl_asan -O0 -DEXE %s -Fe%te.exe
+// RUN: env ASAN_OPTIONS=report_globals=1 %run %te.exe %t.dll 2>&1 | FileCheck %s
+
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+
+extern "C" {
+#if defined(EXE)
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ printf("Usage: %s [client].dll\n", argv[0]);
+ return 101;
+ }
+ const char *dll_name = argv[1];
+
+// CHECK: time to load DLL
+ printf("time to load DLL\n");
+ fflush(0);
+
+// CHECK: in DLL(reason=1)
+// CHECK: in DLL(reason=0)
+// CHECK: in DLL(reason=1)
+// CHECK: in DLL(reason=0)
+// CHECK: in DLL(reason=1)
+// CHECK: in DLL(reason=0)
+ for (int i = 0; i < 30; ++i) {
+ HMODULE dll = LoadLibrary(dll_name);
+ if (dll == NULL)
+ return 3;
+
+ if (!FreeLibrary(dll))
+ return 4;
+ }
+
+// CHECK: All OK!
+ printf("All OK!\n");
+ fflush(0);
+}
+#elif defined(DLL)
+BOOL WINAPI DllMain(HMODULE, DWORD reason, LPVOID) {
+ printf("in DLL(reason=%d)\n", (int)reason);
+ fflush(0);
+ return TRUE;
+}
+#else
+# error oops!
+#endif
+}
diff --git a/test/asan/TestCases/Windows/globals_multiple_dlls.cc b/test/asan/TestCases/Windows/report_globals_vs_freelibrary.cc
index 634e57827..72bf36ad0 100644
--- a/test/asan/TestCases/Windows/globals_multiple_dlls.cc
+++ b/test/asan/TestCases/Windows/report_globals_vs_freelibrary.cc
@@ -1,7 +1,3 @@
-// Make sure everything works even if the main module doesn't have any stack
-// variables, thus doesn't explicitly reference any symbol exported by the
-// runtime thunk.
-//
// RUN: %clang_cl_asan -LD -O0 -DDLL %s -Fe%t.dll
// RUN: %clang_cl_asan -O0 -DEXE %s -Fe%te.exe
// RUN: env ASAN_OPTIONS=report_globals=2 %run %te.exe %t.dll 2>&1 | FileCheck %s
diff --git a/test/asan/TestCases/Windows/stack_array_left_oob.cc b/test/asan/TestCases/Windows/stack_array_left_oob.cc
index 040d855b4..845a1f332 100644
--- a/test/asan/TestCases/Windows/stack_array_left_oob.cc
+++ b/test/asan/TestCases/Windows/stack_array_left_oob.cc
@@ -7,7 +7,7 @@ int main() {
int subscript = -1;
char buffer[42];
buffer[subscript] = 42;
-// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: AddressSanitizer: stack-buffer-underflow on address [[ADDR:0x[0-9a-f]+]]
// CHECK: WRITE of size 1 at [[ADDR]] thread T0
// CHECK-NEXT: {{#0 .* main .*stack_array_left_oob.cc}}:[[@LINE-3]]
// CHECK: Address [[ADDR]] is located in stack of thread T0 at offset [[OFFSET:.*]] in frame
diff --git a/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc b/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc
index 17b9b1bf8..63cb8ae1f 100644
--- a/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc
+++ b/test/asan/TestCases/Windows/thread_stack_array_left_oob.cc
@@ -7,7 +7,7 @@ DWORD WINAPI thread_proc(void *) {
int subscript = -1;
volatile char stack_buffer[42];
stack_buffer[subscript] = 42;
-// CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: AddressSanitizer: stack-buffer-underflow on address [[ADDR:0x[0-9a-f]+]]
// CHECK: WRITE of size 1 at [[ADDR]] thread T1
// CHECK: {{#0 .* thread_proc .*thread_stack_array_left_oob.cc}}:[[@LINE-3]]
// CHECK: Address [[ADDR]] is located in stack of thread T1 at offset {{.*}} in frame
diff --git a/test/asan/TestCases/closed-fds.cc b/test/asan/TestCases/closed-fds.cc
new file mode 100644
index 000000000..604bf8bcf
--- /dev/null
+++ b/test/asan/TestCases/closed-fds.cc
@@ -0,0 +1,30 @@
+// Check that when the program closed its std(in|out|err), running the external
+// symbolizer still works.
+
+// RUN: rm -f %t.log.*
+// RUN: %clangxx_asan -O0 %s -o %t 2>&1 && ASAN_OPTIONS=log_path=%t.log:verbosity=2 not %run %t 2>&1
+// RUN: FileCheck %s --check-prefix=CHECK-FILE < %t.log.*
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ int result = fprintf(stderr, "Closing streams.\n");
+ assert(result > 0);
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+ result = fprintf(stderr, "Can you hear me now?\n");
+ assert(result < 0);
+ char *x = (char *)malloc(10 * sizeof(char));
+ free(x);
+ x[argc] = 'X'; // BOOM
+ // CHECK-FILE: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
+ // CHECK-FILE: {{0x.* at pc 0x.* bp 0x.* sp 0x.*}}
+ // CHECK-FILE: {{WRITE of size 1 at 0x.* thread T0}}
+ // CHECK-FILE: {{ #0 0x.* in main .*closed-fds.cc:}}[[@LINE-4]]
+ return 0;
+}
diff --git a/test/asan/TestCases/Linux/coverage-and-lsan.cc b/test/asan/TestCases/coverage-and-lsan.cc
index 4cb8e2af3..4cb8e2af3 100644
--- a/test/asan/TestCases/Linux/coverage-and-lsan.cc
+++ b/test/asan/TestCases/coverage-and-lsan.cc
diff --git a/test/asan/TestCases/Linux/coverage-caller-callee-total-count.cc b/test/asan/TestCases/coverage-caller-callee-total-count.cc
index 7598f6bc7..7598f6bc7 100644
--- a/test/asan/TestCases/Linux/coverage-caller-callee-total-count.cc
+++ b/test/asan/TestCases/coverage-caller-callee-total-count.cc
diff --git a/test/asan/TestCases/Linux/coverage-caller-callee.cc b/test/asan/TestCases/coverage-caller-callee.cc
index cd318962b..cd318962b 100644
--- a/test/asan/TestCases/Linux/coverage-caller-callee.cc
+++ b/test/asan/TestCases/coverage-caller-callee.cc
diff --git a/test/asan/TestCases/Linux/coverage-disabled.cc b/test/asan/TestCases/coverage-disabled.cc
index cb33542a5..cb33542a5 100644
--- a/test/asan/TestCases/Linux/coverage-disabled.cc
+++ b/test/asan/TestCases/coverage-disabled.cc
diff --git a/test/asan/TestCases/Linux/coverage-levels.cc b/test/asan/TestCases/coverage-levels.cc
index cc196c5a9..63bed650b 100644
--- a/test/asan/TestCases/Linux/coverage-levels.cc
+++ b/test/asan/TestCases/coverage-levels.cc
@@ -6,6 +6,10 @@
// RUN: ASAN_OPTIONS=coverage=1:coverage_bitset=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
// RUN: %clangxx_asan -O1 -fsanitize-coverage=3 %s -o %t
// RUN: ASAN_OPTIONS=coverage=1:coverage_bitset=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3
+// RUN: %clangxx_asan -O1 -fsanitize-coverage=3 -mllvm -sanitizer-coverage-block-threshold=0 %s -o %t
+// RUN: ASAN_OPTIONS=coverage=1:coverage_bitset=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3
+// RUN: %clangxx_asan -O1 -fsanitize-coverage=3 -mllvm -sanitizer-coverage-8bit-counters=1 %s -o %t
+// RUN: ASAN_OPTIONS=coverage=1:coverage_counters=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK_COUNTERS
// RUN: ASAN_OPTIONS=coverage=1:coverage_bitset=0:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3_NOBITSET
// RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3_NOBITSET
@@ -19,11 +23,12 @@ int main(int argc, char **argv) {
sink = 0;
}
-// CHECK1: CovDump: bitset of 1 bits written, 1 bits are set
+// CHECK1: CovDump: bitset of 1 bits written for '{{.*}}', 1 bits are set
// CHECK1: 1 PCs written
-// CHECK2: CovDump: bitset of 3 bits written, 2 bits are set
+// CHECK2: CovDump: bitset of 3 bits written for '{{.*}}', 2 bits are set
// CHECK2: 2 PCs written
-// CHECK3: CovDump: bitset of 4 bits written, 3 bits are set
+// CHECK3: CovDump: bitset of 4 bits written for '{{.*}}', 3 bits are set
// CHECK3: 3 PCs written
// CHECK3_NOBITSET-NOT: bitset of
// CHECK3_NOPCS-NOT: PCs written
+// CHECK_COUNTERS: CovDump: 4 counters written for
diff --git a/test/asan/TestCases/Linux/coverage-maybe-open-file.cc b/test/asan/TestCases/coverage-maybe-open-file.cc
index 4580de411..ca3f92e80 100644
--- a/test/asan/TestCases/Linux/coverage-maybe-open-file.cc
+++ b/test/asan/TestCases/coverage-maybe-open-file.cc
@@ -15,6 +15,7 @@
#include <sanitizer/coverage_interface.h>
+// FIXME: the code below might not work on Windows.
int main(int argc, char **argv) {
int fd = __sanitizer_maybe_open_cov_file("test");
if (fd > 0) {
diff --git a/test/asan/TestCases/coverage-order-pcs.cc b/test/asan/TestCases/coverage-order-pcs.cc
new file mode 100644
index 000000000..076fe1b92
--- /dev/null
+++ b/test/asan/TestCases/coverage-order-pcs.cc
@@ -0,0 +1,56 @@
+// Test coverage_order_pcs=1 flag which orders the PCs by their appearance.
+// RUN: DIR=%T/coverage-order-pcs
+// RUN: rm -rf $DIR
+// RUN: mkdir $DIR
+// RUN: %clangxx_asan -fsanitize-coverage=1 %s -o %t
+// RUN: ASAN_OPTIONS=coverage_dir=$DIR:coverage=1:coverage_order_pcs=0 %run %t
+// RUN: mv $DIR/*sancov $DIR/A
+
+// RUN: ASAN_OPTIONS=coverage_dir=$DIR:coverage=1:coverage_order_pcs=0 %run %t 1
+// RUN: mv $DIR/*sancov $DIR/B
+
+// RUN: ASAN_OPTIONS=coverage_dir=$DIR:coverage=1:coverage_order_pcs=1 %run %t
+// RUN: mv $DIR/*sancov $DIR/C
+
+// RUN: ASAN_OPTIONS=coverage_dir=$DIR:coverage=1:coverage_order_pcs=1 %run %t 1
+// RUN: mv $DIR/*sancov $DIR/D
+//
+// RUN: (%sancov print $DIR/A; %sancov print $DIR/B; %sancov print $DIR/C; %sancov print $DIR/D) | FileCheck %s
+//
+// RUN: rm -rf $DIR
+// Ordering works only in 64-bit mode for now.
+// REQUIRES: asan-64-bits
+#include <stdio.h>
+
+void foo() { fprintf(stderr, "FOO\n"); }
+void bar() { fprintf(stderr, "BAR\n"); }
+
+int main(int argc, char **argv) {
+ if (argc == 2) {
+ foo();
+ bar();
+ } else {
+ bar();
+ foo();
+ }
+}
+
+// Run A: no ordering
+// CHECK: [[FOO:0x[0-9a-f]*]]
+// CHECK-NEXT: [[BAR:0x[0-9a-f]*]]
+// CHECK-NEXT: [[MAIN:0x[0-9a-f]*]]
+//
+// Run B: still no ordering
+// CHECK-NEXT: [[FOO]]
+// CHECK-NEXT: [[BAR]]
+// CHECK-NEXT: [[MAIN]]
+//
+// Run C: MAIN, BAR, FOO
+// CHECK-NEXT: [[MAIN]]
+// CHECK-NEXT: [[BAR]]
+// CHECK-NEXT: [[FOO]]
+//
+// Run D: MAIN, FOO, BAR
+// CHECK-NEXT: [[MAIN]]
+// CHECK-NEXT: [[FOO]]
+// CHECK-NEXT: [[BAR]]
diff --git a/test/asan/TestCases/Linux/coverage-reset.cc b/test/asan/TestCases/coverage-reset.cc
index d3d35e21b..d3d35e21b 100644
--- a/test/asan/TestCases/Linux/coverage-reset.cc
+++ b/test/asan/TestCases/coverage-reset.cc
diff --git a/test/asan/TestCases/Linux/coverage-tracing.cc b/test/asan/TestCases/coverage-tracing.cc
index 49dbb5e95..49dbb5e95 100644
--- a/test/asan/TestCases/Linux/coverage-tracing.cc
+++ b/test/asan/TestCases/coverage-tracing.cc
diff --git a/test/asan/TestCases/debug_stacks.cc b/test/asan/TestCases/debug_stacks.cc
index 57bb54650..15af76dc4 100644
--- a/test/asan/TestCases/debug_stacks.cc
+++ b/test/asan/TestCases/debug_stacks.cc
@@ -2,6 +2,9 @@
// malloc and free stacks.
// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// FIXME: Figure out why allocation/free stack traces may be too short on ARM.
+// REQUIRES: stable-runtime
+
#include <sanitizer/asan_interface.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/test/asan/TestCases/heap-overflow-large.cc b/test/asan/TestCases/heap-overflow-large.cc
index eb2fcc322..566b1158a 100644
--- a/test/asan/TestCases/heap-overflow-large.cc
+++ b/test/asan/TestCases/heap-overflow-large.cc
@@ -15,9 +15,9 @@ int main(int argc, char *argv[]) {
int *x = new int[5];
memset(x, 0, sizeof(x[0]) * 5);
int index = atoi(argv[1]);
- int res = x[index];
+ unsigned res = x[index];
// CHECK: main
// CHECK-NOT: CHECK failed
delete[] x;
- return res ? res : 1;
+ return (res % 10) + 1;
}
diff --git a/test/asan/TestCases/print_summary.cc b/test/asan/TestCases/print_summary.cc
index 79411c529..12dfa2612 100644
--- a/test/asan/TestCases/print_summary.cc
+++ b/test/asan/TestCases/print_summary.cc
@@ -1,14 +1,16 @@
// RUN: %clangxx_asan -O0 %s -o %t
-// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=YES
-// RUN: env ASAN_OPTIONS=print_summary=false not %run %t 2>&1 | FileCheck %s --check-prefix=NO
+// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=SOURCE
+// RUN: env ASAN_OPTIONS=symbolize=false not %run %t 2>&1 | FileCheck %s --check-prefix=MODULE
+// RUN: env ASAN_OPTIONS=print_summary=false not %run %t 2>&1 | FileCheck %s --check-prefix=MISSING
int main() {
char *x = new char[20];
delete[] x;
return x[0];
- // YES: ERROR: AddressSanitizer: heap-use-after-free
- // YES: SUMMARY: AddressSanitizer: heap-use-after-free
- // NO: ERROR: AddressSanitizer: heap-use-after-free
- // NO-NOT: SUMMARY: AddressSanitizer: heap-use-after-free
+ // SOURCE: ERROR: AddressSanitizer: heap-use-after-free
+ // SOURCE: SUMMARY: AddressSanitizer: heap-use-after-free {{.*}}print_summary.cc:[[@LINE-2]]{{.*}} main
+ // MODULE: ERROR: AddressSanitizer: heap-use-after-free
+ // MODULE: SUMMARY: AddressSanitizer: heap-use-after-free ({{.*}}+0x{{.*}})
+ // MISSING: ERROR: AddressSanitizer: heap-use-after-free
+ // MISSING-NOT: SUMMARY
}
-
diff --git a/test/asan/TestCases/strip_path_prefix.c b/test/asan/TestCases/strip_path_prefix.c
index 4556e9031..c441eac92 100644
--- a/test/asan/TestCases/strip_path_prefix.c
+++ b/test/asan/TestCases/strip_path_prefix.c
@@ -1,5 +1,5 @@
// RUN: %clang_asan -O2 %s -o %t
-// RUN: env ASAN_OPTIONS="strip_path_prefix='/'" not %run %t 2>&1 | FileCheck %s
+// RUN: env ASAN_OPTIONS="strip_path_prefix='%S/'" not %run %t 2>&1 | FileCheck %s
#include <stdlib.h>
int main() {
@@ -8,5 +8,5 @@ int main() {
return x[5];
// Check that paths in error report don't start with slash.
// CHECK: heap-use-after-free
- // CHECK-NOT: #0 0x{{.*}} ({{[/].*}})
+ // CHECK: #0 0x{{.*}} in main strip_path_prefix.c:[[@LINE-3]]
}
diff --git a/test/asan/TestCases/suppressions-exec-relative-location.cc b/test/asan/TestCases/suppressions-exec-relative-location.cc
new file mode 100644
index 000000000..cc69b7a6e
--- /dev/null
+++ b/test/asan/TestCases/suppressions-exec-relative-location.cc
@@ -0,0 +1,47 @@
+// Check that without suppressions, we catch the issue.
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
+
+// If the executable is started from a different location, we should still
+// find the suppression file located relative to the location of the executable.
+// RUN: rm -rf %T/suppressions-exec-relative-location
+// RUN: mkdir -p %T/suppressions-exec-relative-location
+// RUN: %clangxx_asan -O0 %s -o %T/suppressions-exec-relative-location/exec
+// RUN: echo "interceptor_via_fun:crash_function" > \
+// RUN: %T/suppressions-exec-relative-location/supp.txt
+// RUN: ASAN_OPTIONS="suppressions=supp.txt" \
+// RUN: %run %T/suppressions-exec-relative-location/exec 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-IGNORE %s
+// RUN: rm -rf %T/suppressions-exec-relative-location
+
+// If the wrong absolute path is given, we don't try to construct
+// a relative path with it.
+// RUN: ASAN_OPTIONS="suppressions='/absolute/path'" not %run %t 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-WRONG-FILE-NAME %s
+
+// Test that we reject directory as filename.
+// RUN: ASAN_OPTIONS="suppressions='folder/only/'" not %run %t 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-WRONG-FILE-NAME %s
+
+// XFAIL: android
+// XFAIL: win32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void crash_function() {
+ char *a = (char *)malloc(6);
+ free(a);
+ size_t len = strlen(a); // BOOM
+ fprintf(stderr, "strlen ignored, len = %zu\n", len);
+}
+
+int main() {
+ crash_function();
+}
+
+// CHECK-CRASH: AddressSanitizer: heap-use-after-free
+// CHECK-IGNORE-NOT: AddressSanitizer: heap-buffer-overflow
+// CHECK-IGNORE: ignored
+// CHECK-WRONG-FILE-NAME: failed to read suppressions file
diff --git a/test/builtins/Unit/divtc3_test.c b/test/builtins/Unit/divtc3_test.c
index 7bb74d755..50918d68f 100644
--- a/test/builtins/Unit/divtc3_test.c
+++ b/test/builtins/Unit/divtc3_test.c
@@ -11,12 +11,13 @@
//
//===----------------------------------------------------------------------===//
+#include <stdio.h>
+
#if _ARCH_PPC
#include "int_lib.h"
#include <math.h>
#include <complex.h>
-#include <stdio.h>
// Returns: the quotient of (a + ib) / (c + id)
diff --git a/test/builtins/Unit/fixtfsi_test.c b/test/builtins/Unit/fixtfsi_test.c
new file mode 100644
index 000000000..45ad0d243
--- /dev/null
+++ b/test/builtins/Unit/fixtfsi_test.c
@@ -0,0 +1,65 @@
+//===--------------- fixtfsi_test.c - Test __fixtfsi ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file tests __fixtfsi for the compiler_rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+
+#if __LDBL_MANT_DIG__ == 113
+
+#include "fp_test.h"
+
+int __fixtfsi(long double a);
+
+int test__fixtfsi(long double a, int expected)
+{
+ int x = __fixtfsi(a);
+ int ret = (x != expected);
+
+ if (ret){
+ printf("error in test__fixtfsi(%.20Lf) = %d, "
+ "expected %d\n", a, x, expected);
+ }
+ return ret;
+}
+
+char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0};
+
+#endif
+
+int main()
+{
+#if __LDBL_MANT_DIG__ == 113
+ if (test__fixtfsi(makeInf128(), 0x7fffffff))
+ return 1;
+ if (test__fixtfsi(0, 0x0))
+ return 1;
+ if (test__fixtfsi(0x1.23456789abcdefp+5, 0x24))
+ return 1;
+ if (test__fixtfsi(0x1.23456789abcdefp-3, 0x0))
+ return 1;
+ if (test__fixtfsi(0x1.23456789abcdefp+20, 0x123456))
+ return 1;
+ if (test__fixtfsi(0x1.23456789abcdefp+40, 0x7fffffff))
+ return 1;
+ if (test__fixtfsi(0x1.23456789abcdefp+256, 0x7fffffff))
+ return 1;
+ if (test__fixtfsi(-0x1.23456789abcdefp+20, 0xffedcbaa))
+ return 1;
+ if (test__fixtfsi(-0x1.23456789abcdefp+40, 0x80000001))
+ return 1;
+
+#else
+ printf("skipped\n");
+
+#endif
+ return 0;
+}
diff --git a/test/builtins/Unit/fixunstfdi_test.c b/test/builtins/Unit/fixunstfdi_test.c
index d0a5db7a9..a5a946050 100644
--- a/test/builtins/Unit/fixunstfdi_test.c
+++ b/test/builtins/Unit/fixunstfdi_test.c
@@ -11,10 +11,11 @@
//
//===----------------------------------------------------------------------===//
+#include <stdio.h>
+
#if _ARCH_PPC
#include "int_lib.h"
-#include <stdio.h>
// Returns: convert a to a unsigned long long, rounding toward zero.
// Negative values all become zero.
diff --git a/test/builtins/Unit/fixunstfsi_test.c b/test/builtins/Unit/fixunstfsi_test.c
new file mode 100644
index 000000000..4bf8fdec6
--- /dev/null
+++ b/test/builtins/Unit/fixunstfsi_test.c
@@ -0,0 +1,64 @@
+//===--------------- fixunstfsi_test.c - Test __fixunstfsi ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file tests __fixunstfsi for the compiler_rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+
+#if __LDBL_MANT_DIG__ == 113
+
+#include "fp_test.h"
+
+unsigned int __fixunstfsi(long double a);
+
+int test__fixunstfsi(long double a, unsigned int expected)
+{
+ unsigned int x = __fixunstfsi(a);
+ int ret = (x != expected);
+
+ if (ret)
+ {
+ printf("error in test__fixunstfsi(%.20Lf) = %u, "
+ "expected %u\n", a, x, expected);
+ }
+ return ret;
+}
+
+char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0};
+
+#endif
+
+int main()
+{
+#if __LDBL_MANT_DIG__ == 113
+ if (test__fixunstfsi(makeInf128(), UINT32_C(0xffffffff)))
+ return 1;
+ if (test__fixunstfsi(0, UINT32_C(0x0)))
+ return 1;
+ if (test__fixunstfsi(0x1.23456789abcdefp+5, UINT32_C(0x24)))
+ return 1;
+ if (test__fixunstfsi(0x1.23456789abcdefp-3, UINT32_C(0x0)))
+ return 1;
+ if (test__fixunstfsi(0x1.23456789abcdefp+20, UINT32_C(0x123456)))
+ return 1;
+ if (test__fixunstfsi(0x1.23456789abcdefp+40, UINT32_C(0xffffffff)))
+ return 1;
+ if (test__fixunstfsi(0x1.23456789abcdefp+256, UINT32_C(0xffffffff)))
+ return 1;
+ if (test__fixunstfsi(-0x1.23456789abcdefp+3, UINT32_C(0x0)))
+ return 1;
+
+#else
+ printf("skipped\n");
+
+#endif
+ return 0;
+}
diff --git a/test/builtins/Unit/multc3_test.c b/test/builtins/Unit/multc3_test.c
index f8c66c0e4..8d3480157 100644
--- a/test/builtins/Unit/multc3_test.c
+++ b/test/builtins/Unit/multc3_test.c
@@ -11,12 +11,13 @@
//
//===----------------------------------------------------------------------===//
+#include <stdio.h>
+
#if _ARCH_PPC
#include "int_lib.h"
#include <math.h>
#include <complex.h>
-#include <stdio.h>
// Returns: the product of a + ib and c + id
diff --git a/test/builtins/Unit/powitf2_test.c b/test/builtins/Unit/powitf2_test.c
index 817cb1130..dfe758837 100644
--- a/test/builtins/Unit/powitf2_test.c
+++ b/test/builtins/Unit/powitf2_test.c
@@ -11,10 +11,11 @@
//
//===----------------------------------------------------------------------===//
+#include <stdio.h>
+
#if _ARCH_PPC
#include "int_lib.h"
-#include <stdio.h>
#include <math.h>
// Returns: a ^ b
diff --git a/test/cfi/CMakeLists.txt b/test/cfi/CMakeLists.txt
index 5750bd8a4..625e3ff11 100644
--- a/test/cfi/CMakeLists.txt
+++ b/test/cfi/CMakeLists.txt
@@ -15,6 +15,11 @@ if(NOT COMPILER_RT_STANDALONE_BUILD)
LLVMgold
)
endif()
+ if(APPLE)
+ list(APPEND CFI_TEST_DEPS
+ LTO
+ )
+ endif()
endif()
add_lit_testsuite(check-cfi "Running the cfi regression tests"
diff --git a/test/cfi/bad-cast.cpp b/test/cfi/bad-cast.cpp
new file mode 100644
index 000000000..39d8a351b
--- /dev/null
+++ b/test/cfi/bad-cast.cpp
@@ -0,0 +1,136 @@
+// RUN: %clangxx_cfi -o %t %s
+// RUN: not --crash %t a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: not --crash %t g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t h 2>&1 | FileCheck --check-prefix=PASS %s
+
+// RUN: %clangxx_cfi -DB32 -o %t %s
+// RUN: not --crash %t a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: not --crash %t g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t h 2>&1 | FileCheck --check-prefix=PASS %s
+
+// RUN: %clangxx_cfi -DB64 -o %t %s
+// RUN: not --crash %t a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: not --crash %t g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t h 2>&1 | FileCheck --check-prefix=PASS %s
+
+// RUN: %clangxx_cfi -DBM -o %t %s
+// RUN: not --crash %t a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: not --crash %t g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %t h 2>&1 | FileCheck --check-prefix=PASS %s
+
+// RUN: %clangxx_cfi -fsanitize=cfi-cast-strict -o %t %s
+// RUN: not --crash %t a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t d 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t e 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t f 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: not --crash %t h 2>&1 | FileCheck --check-prefix=FAIL %s
+
+// RUN: %clangxx -o %t %s
+// RUN: %t a 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t b 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t c 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t g 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %t h 2>&1 | FileCheck --check-prefix=PASS %s
+
+// Tests that the CFI enforcement detects bad casts.
+
+#include <stdio.h>
+#include <utility>
+#include "utils.h"
+
+struct A {
+ virtual void f();
+};
+
+void A::f() {}
+
+struct B : A {
+ virtual void f();
+};
+
+void B::f() {}
+
+struct C : A {
+};
+
+int main(int argc, char **argv) {
+#ifdef B32
+ break_optimization(new Deriver<B, 0>);
+#endif
+
+#ifdef B64
+ break_optimization(new Deriver<B, 0>);
+ break_optimization(new Deriver<B, 1>);
+#endif
+
+#ifdef BM
+ break_optimization(new Deriver<B, 0>);
+ break_optimization(new Deriver<B, 1>);
+ break_optimization(new Deriver<B, 2>);
+#endif
+
+ B *b = new B;
+ break_optimization(b);
+
+ // FAIL: 1
+ // PASS: 1
+ fprintf(stderr, "1\n");
+
+ A a;
+ switch (argv[1][0]) {
+ case 'a':
+ static_cast<B *>(&a); // UB
+ break;
+ case 'b':
+ static_cast<B &>(a); // UB
+ break;
+ case 'c':
+ static_cast<B &&>(a); // UB
+ break;
+ case 'd':
+ static_cast<C *>(&a); // UB, strict only
+ break;
+ case 'e':
+ static_cast<C &>(a); // UB, strict only
+ break;
+ case 'f':
+ static_cast<C &&>(a); // UB, strict only
+ break;
+ case 'g':
+ static_cast<B *>(static_cast<void *>(&a)); // Non-UB bad cast
+ break;
+ case 'h':
+ static_cast<C *>(static_cast<void *>(&a)); // Non-UB bad cast, strict only
+ break;
+ }
+
+ // FAIL-NOT: 2
+ // PASS: 2
+ fprintf(stderr, "2\n");
+}
diff --git a/test/cfi/sibling.cpp b/test/cfi/sibling.cpp
new file mode 100644
index 000000000..c8b95e9de
--- /dev/null
+++ b/test/cfi/sibling.cpp
@@ -0,0 +1,67 @@
+// XFAIL: *
+
+// RUN: %clangxx_cfi -o %t %s
+// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
+
+// RUN: %clangxx_cfi -DB32 -o %t %s
+// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
+
+// RUN: %clangxx_cfi -DB64 -o %t %s
+// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
+
+// RUN: %clangxx_cfi -DBM -o %t %s
+// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
+
+// RUN: %clangxx -o %t %s
+// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s
+
+// Tests that the CFI enforcement distinguishes betwen non-overriding siblings.
+// XFAILed as not implemented yet.
+
+#include <stdio.h>
+#include "utils.h"
+
+struct A {
+ virtual void f();
+};
+
+void A::f() {}
+
+struct B : A {
+ virtual void f();
+};
+
+void B::f() {}
+
+struct C : A {
+};
+
+int main() {
+#ifdef B32
+ break_optimization(new Deriver<B, 0>);
+#endif
+
+#ifdef B64
+ break_optimization(new Deriver<B, 0>);
+ break_optimization(new Deriver<B, 1>);
+#endif
+
+#ifdef BM
+ break_optimization(new Deriver<B, 0>);
+ break_optimization(new Deriver<B, 1>);
+ break_optimization(new Deriver<B, 2>);
+#endif
+
+ B *b = new B;
+ break_optimization(b);
+
+ // CFI: 1
+ // NCFI: 1
+ fprintf(stderr, "1\n");
+
+ ((C *)b)->f(); // UB here
+
+ // CFI-NOT: 2
+ // NCFI: 2
+ fprintf(stderr, "2\n");
+}
diff --git a/test/dfsan/basic.c b/test/dfsan/basic.c
index 6582727e5..990fd1161 100644
--- a/test/dfsan/basic.c
+++ b/test/dfsan/basic.c
@@ -1,5 +1,5 @@
-// RUN: %clang_dfsan -m64 %s -o %t && %run %t
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %s -o %t && %run %t
+// RUN: %clang_dfsan %s -o %t && %run %t
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && %run %t
// Tests that labels are propagated through loads and stores.
diff --git a/test/dfsan/custom.cc b/test/dfsan/custom.cc
index d7bb3e307..bdd7cf511 100644
--- a/test/dfsan/custom.cc
+++ b/test/dfsan/custom.cc
@@ -1,7 +1,7 @@
-// RUN: %clang_dfsan -m64 %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
-// RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES -m64 %s -o %t && %run %t
-// RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES -mllvm -dfsan-args-abi -m64 %s -o %t && %run %t
+// RUN: %clang_dfsan %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
+// 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
// Tests custom implementations of various glibc functions.
diff --git a/test/dfsan/dump_labels.c b/test/dfsan/dump_labels.c
index 67801af18..3bbc1e2c0 100644
--- a/test/dfsan/dump_labels.c
+++ b/test/dfsan/dump_labels.c
@@ -1,4 +1,4 @@
-// RUN: %clang_dfsan -m64 %s -o %t
+// RUN: %clang_dfsan %s -o %t
// RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout %run %t 2>&1 | FileCheck %s
// RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout not %run %t c 2>&1 | FileCheck %s --check-prefix=CHECK-OOL
// RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout not %run %t u 2>&1 | FileCheck %s --check-prefix=CHECK-OOL
diff --git a/test/dfsan/flags.c b/test/dfsan/flags.c
index 79069b96f..914f54f42 100644
--- a/test/dfsan/flags.c
+++ b/test/dfsan/flags.c
@@ -1,6 +1,6 @@
-// RUN: %clang_dfsan -m64 %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && %run %t 2>&1 | FileCheck %s
-// RUN: %clang_dfsan -m64 %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && DFSAN_OPTIONS=warn_unimplemented=0 %run %t 2>&1 | count 0
-// RUN: %clang_dfsan -m64 %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && DFSAN_OPTIONS=warn_nonzero_labels=1 %run %t 2>&1 | FileCheck --check-prefix=CHECK-NONZERO %s
+// RUN: %clang_dfsan %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clang_dfsan %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && DFSAN_OPTIONS=warn_unimplemented=0 %run %t 2>&1 | count 0
+// RUN: %clang_dfsan %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && DFSAN_OPTIONS=warn_nonzero_labels=1 %run %t 2>&1 | FileCheck --check-prefix=CHECK-NONZERO %s
// Tests that flags work correctly.
diff --git a/test/dfsan/fncall.c b/test/dfsan/fncall.c
index e780f3145..458fba66d 100644
--- a/test/dfsan/fncall.c
+++ b/test/dfsan/fncall.c
@@ -1,5 +1,5 @@
-// RUN: %clang_dfsan -m64 %s -o %t && %run %t
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %s -o %t && %run %t
+// RUN: %clang_dfsan %s -o %t && %run %t
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && %run %t
// Tests that labels are propagated through function calls.
diff --git a/test/dfsan/label_count.c b/test/dfsan/label_count.c
index a4b608701..b42ce5824 100644
--- a/test/dfsan/label_count.c
+++ b/test/dfsan/label_count.c
@@ -1,11 +1,11 @@
-// RUN: %clang_dfsan -DLIB -m64 -c %s -o %t.lib.o && \
-// RUN: %clang_dfsan -m64 -c %s -o %t.o && \
-// RUN: %clang_dfsan -m64 %t.lib.o %t.o -o %t.bin && \
+// RUN: %clang_dfsan -DLIB -c %s -o %t.lib.o && \
+// RUN: %clang_dfsan -c %s -o %t.o && \
+// RUN: %clang_dfsan %t.lib.o %t.o -o %t.bin && \
// RUN: %run %t.bin
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 -DLIB -c %s -o %t.lib.o && \
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 -c %s -o %t.o && \
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %t.o %t.lib.o -o %t.bin && \
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi -DLIB -c %s -o %t.lib.o && \
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi -c %s -o %t.o && \
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi %t.o %t.lib.o -o %t.bin && \
// RUN: %run %t.bin
#include <sanitizer/dfsan_interface.h>
diff --git a/test/dfsan/lit.cfg b/test/dfsan/lit.cfg
index d4adb9a51..e4d4e8f57 100644
--- a/test/dfsan/lit.cfg
+++ b/test/dfsan/lit.cfg
@@ -9,7 +9,7 @@ config.name = 'DataFlowSanitizer'
config.test_source_root = os.path.dirname(__file__)
# Setup default compiler flags used with -fsanitize=dataflow option.
-clang_dfsan_cflags = ["-fsanitize=dataflow"]
+clang_dfsan_cflags = ["-fsanitize=dataflow", "-m64"]
clang_dfsan_cxxflags = config.cxx_mode_flags + clang_dfsan_cflags
def build_invocation(compile_flags):
diff --git a/test/dfsan/propagate.c b/test/dfsan/propagate.c
index 733538cb1..c30a087d6 100644
--- a/test/dfsan/propagate.c
+++ b/test/dfsan/propagate.c
@@ -1,5 +1,5 @@
-// RUN: %clang_dfsan -m64 %s -o %t && %run %t
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %s -o %t && %run %t
+// RUN: %clang_dfsan %s -o %t && %run %t
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && %run %t
// Tests that labels are propagated through computation and that union labels
// are properly created.
diff --git a/test/dfsan/vararg.c b/test/dfsan/vararg.c
index 2227ba715..f51e39c71 100644
--- a/test/dfsan/vararg.c
+++ b/test/dfsan/vararg.c
@@ -1,7 +1,7 @@
-// RUN: %clang_dfsan -m64 %s -o %t
+// RUN: %clang_dfsan %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
// RUN: %run %t foo
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %s -o %t
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
// RUN: %run %t foo
diff --git a/test/dfsan/write_callback.c b/test/dfsan/write_callback.c
index bb35f3250..3ba027a0a 100644
--- a/test/dfsan/write_callback.c
+++ b/test/dfsan/write_callback.c
@@ -1,5 +1,5 @@
-// RUN: %clang_dfsan -m64 %s -o %t && %run %t | FileCheck %s
-// RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %s -o %t && %run %t | FileCheck %s
+// RUN: %clang_dfsan %s -o %t && %run %t | FileCheck %s
+// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && %run %t | FileCheck %s
// Tests that the custom implementation of write() does writes with or without
// a callback set using dfsan_set_write_callback().
diff --git a/test/msan/Linux/getresid.cc b/test/msan/Linux/getresid.cc
index 385351dfd..f3c0914b5 100644
--- a/test/msan/Linux/getresid.cc
+++ b/test/msan/Linux/getresid.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p 2>&1
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&1
#include <assert.h>
#include <unistd.h>
diff --git a/test/msan/Linux/glob.cc b/test/msan/Linux/glob.cc
index 8604e4d76..1481861a0 100644
--- a/test/msan/Linux/glob.cc
+++ b/test/msan/Linux/glob.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&1 | FileCheck %s
#include <assert.h>
#include <glob.h>
diff --git a/test/msan/Linux/glob_altdirfunc.cc b/test/msan/Linux/glob_altdirfunc.cc
index 2c02e735e..cb7fe09cb 100644
--- a/test/msan/Linux/glob_altdirfunc.cc
+++ b/test/msan/Linux/glob_altdirfunc.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&1 | FileCheck %s
#include <assert.h>
#include <glob.h>
diff --git a/test/msan/Linux/glob_nomatch.cc b/test/msan/Linux/glob_nomatch.cc
index bc35c30d6..fa132c813 100644
--- a/test/msan/Linux/glob_nomatch.cc
+++ b/test/msan/Linux/glob_nomatch.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p
#include <assert.h>
#include <glob.h>
diff --git a/test/msan/Linux/sunrpc.cc b/test/msan/Linux/sunrpc.cc
index 78645a7dc..c92ad632c 100644
--- a/test/msan/Linux/sunrpc.cc
+++ b/test/msan/Linux/sunrpc.cc
@@ -1,14 +1,14 @@
-// RUN: %clangxx_msan -m64 -g -O0 -DTYPE=int -DFN=xdr_int %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DTYPE=int -DFN=xdr_int %s -o %t && \
// RUN: %run %t 2>&1
-// RUN: %clangxx_msan -m64 -g -O0 -DTYPE=int -DFN=xdr_int -DUNINIT=1 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DTYPE=int -DFN=xdr_int -DUNINIT=1 %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -m64 -g -O0 -DTYPE=double -DFN=xdr_double %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DTYPE=double -DFN=xdr_double %s -o %t && \
// RUN: %run %t 2>&1
-// RUN: %clangxx_msan -m64 -g -O0 -DTYPE=double -DFN=xdr_double -DUNINIT=1 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DTYPE=double -DFN=xdr_double -DUNINIT=1 %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -m64 -g -O0 -DTYPE=u_quad_t -DFN=xdr_u_longlong_t %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DTYPE=u_quad_t -DFN=xdr_u_longlong_t %s -o %t && \
// RUN: %run %t 2>&1
-// RUN: %clangxx_msan -m64 -g -O0 -DTYPE=u_quad_t -DFN=xdr_u_longlong_t -DUNINIT=1 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DTYPE=u_quad_t -DFN=xdr_u_longlong_t -DUNINIT=1 %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
#include <assert.h>
diff --git a/test/msan/Linux/sunrpc_bytes.cc b/test/msan/Linux/sunrpc_bytes.cc
index f0c35746f..477637af2 100644
--- a/test/msan/Linux/sunrpc_bytes.cc
+++ b/test/msan/Linux/sunrpc_bytes.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -g -O0 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 %s -o %t && \
// RUN: %run %t 2>&1
-// RUN: %clangxx_msan -m64 -g -O0 -DUNINIT=1 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DUNINIT=1 %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
#include <assert.h>
diff --git a/test/msan/Linux/sunrpc_string.cc b/test/msan/Linux/sunrpc_string.cc
index 3f44a96d1..350222f5c 100644
--- a/test/msan/Linux/sunrpc_string.cc
+++ b/test/msan/Linux/sunrpc_string.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -g -O0 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 %s -o %t && \
// RUN: %run %t 2>&1
-// RUN: %clangxx_msan -m64 -g -O0 -DUNINIT=1 %s -o %t && \
+// RUN: %clangxx_msan -g -O0 -DUNINIT=1 %s -o %t && \
// RUN: not %run %t 2>&1 | FileCheck %s
#include <assert.h>
diff --git a/test/msan/Linux/syscalls.cc b/test/msan/Linux/syscalls.cc
index 4dd97e745..78dba3663 100644
--- a/test/msan/Linux/syscalls.cc
+++ b/test/msan/Linux/syscalls.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t 2>&1
#include <assert.h>
#include <errno.h>
diff --git a/test/msan/Linux/tcgetattr.cc b/test/msan/Linux/tcgetattr.cc
index e1425b84f..454b7fd15 100644
--- a/test/msan/Linux/tcgetattr.cc
+++ b/test/msan/Linux/tcgetattr.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p
#include <assert.h>
#include <glob.h>
diff --git a/test/msan/Linux/xattr.cc b/test/msan/Linux/xattr.cc
index 1beba117d..86cc2cd47 100644
--- a/test/msan/Linux/xattr.cc
+++ b/test/msan/Linux/xattr.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p 2>&1
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&1
#include <argz.h>
#include <assert.h>
diff --git a/test/msan/backtrace.cc b/test/msan/backtrace.cc
index 473e0ae8f..b6cfcbed4 100644
--- a/test/msan/backtrace.cc
+++ b/test/msan/backtrace.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
#include <assert.h>
#include <execinfo.h>
diff --git a/test/msan/c-strdup.c b/test/msan/c-strdup.c
index 059300e42..b1e02b914 100644
--- a/test/msan/c-strdup.c
+++ b/test/msan/c-strdup.c
@@ -1,7 +1,7 @@
-// RUN: %clang_msan -m64 -O0 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clang_msan -m64 -O1 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clang_msan -m64 -O2 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clang_msan -m64 -O3 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clang_msan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clang_msan -O1 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clang_msan -O2 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clang_msan -O3 %s -o %t && %run %t >%t.out 2>&1
// Test that strdup in C programs is intercepted.
// GLibC headers translate strdup to __strdup at -O1 and higher.
diff --git a/test/msan/chained_origin.cc b/test/msan/chained_origin.cc
index 336bbd852..ae72c10b6 100644
--- a/test/msan/chained_origin.cc
+++ b/test/msan/chained_origin.cc
@@ -1,17 +1,17 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t && \
+// 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: %clangxx_msan -fsanitize-memory-track-origins=2 -DHEAP=1 -m64 -O3 %s -o %t && \
+// 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: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t && \
+// 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: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -DHEAP=1 -m64 -O3 %s -o %t && \
+// 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
diff --git a/test/msan/chained_origin_empty_stack.cc b/test/msan/chained_origin_empty_stack.cc
index 36727e3d7..f1ed66b75 100644
--- a/test/msan/chained_origin_empty_stack.cc
+++ b/test/msan/chained_origin_empty_stack.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t && \
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O3 %s -o %t && \
// RUN: MSAN_OPTIONS=store_context_size=1 not %run %t 2>&1 | FileCheck %s
// Test that stack trace for the intermediate store is not empty.
diff --git a/test/msan/chained_origin_limits.cc b/test/msan/chained_origin_limits.cc
index 0cc57f32a..90fd09a86 100644
--- a/test/msan/chained_origin_limits.cc
+++ b/test/msan/chained_origin_limits.cc
@@ -1,7 +1,7 @@
// This test program creates a very large number of unique histories.
// Heap origin.
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O3 %s -o %t
// RUN: MSAN_OPTIONS=origin_history_size=7 not %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
@@ -16,7 +16,7 @@
// RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
// Stack origin.
-// RUN: %clangxx_msan -DSTACK -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t
+// RUN: %clangxx_msan -DSTACK -fsanitize-memory-track-origins=2 -O3 %s -o %t
// RUN: MSAN_OPTIONS=origin_history_size=7 not %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
@@ -32,7 +32,7 @@
// Heap origin, with calls.
-// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t
+// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -O3 %s -o %t
// RUN: MSAN_OPTIONS=origin_history_size=7 not %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
@@ -48,7 +48,7 @@
// Stack origin, with calls.
-// RUN: %clangxx_msan -DSTACK -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t
+// RUN: %clangxx_msan -DSTACK -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -O3 %s -o %t
// RUN: MSAN_OPTIONS=origin_history_size=7 not %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK7 < %t.out
diff --git a/test/msan/chained_origin_memcpy.cc b/test/msan/chained_origin_memcpy.cc
index f4c2f7fca..3fe0b77a0 100644
--- a/test/msan/chained_origin_memcpy.cc
+++ b/test/msan/chained_origin_memcpy.cc
@@ -1,17 +1,17 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -DOFFSET=0 -O3 %s -o %t && \
+// 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: %clangxx_msan -fsanitize-memory-track-origins=2 -DOFFSET=10 -m64 -O3 %s -o %t && \
+// 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: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -m64 -DOFFSET=0 -O3 %s -o %t && \
+// 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: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -DOFFSET=10 -m64 -O3 %s -o %t && \
+// 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
diff --git a/test/msan/chained_origin_with_signals.cc b/test/msan/chained_origin_with_signals.cc
index 2841e34a1..43dbdcca7 100644
--- a/test/msan/chained_origin_with_signals.cc
+++ b/test/msan/chained_origin_with_signals.cc
@@ -2,11 +2,11 @@
// This is, in fact, undesired behavior caused by our chained origins
// implementation being not async-signal-safe.
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t && \
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O3 %s -o %t && \
// RUN: not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -mllvm -msan-instrumentation-with-call-threshold=0 -fsanitize-memory-track-origins=2 -m64 -O3 %s -o %t && \
+// 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 < %t.out
diff --git a/test/msan/check_mem_is_initialized.cc b/test/msan/check_mem_is_initialized.cc
index 7d2328810..e1d3b117e 100644
--- a/test/msan/check_mem_is_initialized.cc
+++ b/test/msan/check_mem_is_initialized.cc
@@ -1,19 +1,19 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O1 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
#include <sanitizer/msan_interface.h>
diff --git a/test/msan/cxa_atexit.cc b/test/msan/cxa_atexit.cc
index 0aa36ecee..70384b9c9 100644
--- a/test/msan/cxa_atexit.cc
+++ b/test/msan/cxa_atexit.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p
// PR17377: C++ module destructors get stale argument shadow.
diff --git a/test/msan/death-callback.cc b/test/msan/death-callback.cc
index 6d0488339..08cf2911b 100644
--- a/test/msan/death-callback.cc
+++ b/test/msan/death-callback.cc
@@ -1,10 +1,10 @@
-// RUN: %clangxx_msan -m64 -DERROR %s -o %t && not %run %t 2>&1 | \
+// RUN: %clangxx_msan -DERROR %s -o %t && not %run %t 2>&1 | \
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOCB
-// RUN: %clangxx_msan -m64 -DERROR -DMSANCB_SET %s -o %t && not %run %t 2>&1 | \
+// RUN: %clangxx_msan -DERROR -DMSANCB_SET %s -o %t && not %run %t 2>&1 | \
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CB
-// RUN: %clangxx_msan -m64 -DERROR -DMSANCB_SET -DMSANCB_CLEAR %s -o %t && not %run %t 2>&1 | \
+// RUN: %clangxx_msan -DERROR -DMSANCB_SET -DMSANCB_CLEAR %s -o %t && not %run %t 2>&1 | \
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOCB
-// RUN: %clangxx_msan -m64 -DMSANCB_SET %s -o %t && %run %t 2>&1 | \
+// RUN: %clangxx_msan -DMSANCB_SET %s -o %t && %run %t 2>&1 | \
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOCB
#include <sanitizer/msan_interface.h>
diff --git a/test/msan/dlerror.cc b/test/msan/dlerror.cc
index 2c726d360..d5510b65c 100644
--- a/test/msan/dlerror.cc
+++ b/test/msan/dlerror.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
#include <assert.h>
#include <dlfcn.h>
diff --git a/test/msan/dso-origin.cc b/test/msan/dso-origin.cc
index ba008c007..7f6244984 100644
--- a/test/msan/dso-origin.cc
+++ b/test/msan/dso-origin.cc
@@ -1,7 +1,7 @@
// Build a library with origin tracking and an executable w/o origin tracking.
// Test that origin tracking is enabled at runtime.
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -DBUILD_SO -fPIC -shared -o %t-so.so
-// RUN: %clangxx_msan -m64 -O0 %s %t-so.so -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -DBUILD_SO -fPIC -shared -o %t-so.so
+// RUN: %clangxx_msan -O0 %s %t-so.so -o %t && not %run %t 2>&1 | FileCheck %s
#ifdef BUILD_SO
diff --git a/test/msan/dtls_test.c b/test/msan/dtls_test.c
index cb88ede2f..4036f71a7 100644
--- a/test/msan/dtls_test.c
+++ b/test/msan/dtls_test.c
@@ -1,5 +1,5 @@
-/* RUN: %clang_msan -g -m64 %s -o %t
- RUN: %clang_msan -g -m64 %s -DBUILD_SO -fPIC -o %t-so.so -shared
+/* RUN: %clang_msan -g %s -o %t
+ RUN: %clang_msan -g %s -DBUILD_SO -fPIC -o %t-so.so -shared
RUN: %run %t 2>&1
Regression test for a bug in msan/glibc integration,
diff --git a/test/msan/errno.cc b/test/msan/errno.cc
index 8af8eb5ee..6ed0fd410 100644
--- a/test/msan/errno.cc
+++ b/test/msan/errno.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
#include <assert.h>
#include <errno.h>
diff --git a/test/msan/fork.cc b/test/msan/fork.cc
index 10de8a937..78a62d549 100644
--- a/test/msan/fork.cc
+++ b/test/msan/fork.cc
@@ -2,7 +2,7 @@
// Run a number of threads that create new chained origins, then fork
// and verify that origin reads do not deadlock in the child process.
-// RUN: %clangxx_msan -std=c++11 -fsanitize-memory-track-origins=2 -g -m64 -O3 %s -o %t
+// 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
// Fun fact: if test output is redirected to a file (as opposed to
diff --git a/test/msan/ftime.cc b/test/msan/ftime.cc
index 2d0935d18..5ed9358f0 100644
--- a/test/msan/ftime.cc
+++ b/test/msan/ftime.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
#include <assert.h>
#include <sys/timeb.h>
diff --git a/test/msan/getaddrinfo-positive.cc b/test/msan/getaddrinfo-positive.cc
index 7658cd504..45c1b604d 100644
--- a/test/msan/getaddrinfo-positive.cc
+++ b/test/msan/getaddrinfo-positive.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
#include <sys/types.h>
diff --git a/test/msan/getaddrinfo.cc b/test/msan/getaddrinfo.cc
index abab8bd78..c9dcf3ecb 100644
--- a/test/msan/getaddrinfo.cc
+++ b/test/msan/getaddrinfo.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
#include <sys/types.h>
#include <sys/socket.h>
diff --git a/test/msan/getc_unlocked.c b/test/msan/getc_unlocked.c
index 7df958ad6..8468fed5c 100644
--- a/test/msan/getc_unlocked.c
+++ b/test/msan/getc_unlocked.c
@@ -1,12 +1,12 @@
-// RUN: %clangxx_msan -DGETC -m64 -O0 -g -xc++ %s -o %t && %run %t
-// RUN: %clangxx_msan -DGETC -m64 -O3 -g -xc++ %s -o %t && %run %t
-// RUN: %clang_msan -DGETC -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clang_msan -DGETC -m64 -O3 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -DGETC -O0 -g -xc++ %s -o %t && %run %t
+// RUN: %clangxx_msan -DGETC -O3 -g -xc++ %s -o %t && %run %t
+// RUN: %clang_msan -DGETC -O0 -g %s -o %t && %run %t
+// RUN: %clang_msan -DGETC -O3 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -DGETCHAR -m64 -O0 -g -xc++ %s -o %t && %run %t
-// RUN: %clangxx_msan -DGETCHAR -m64 -O3 -g -xc++ %s -o %t && %run %t
-// RUN: %clang_msan -DGETCHAR -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clang_msan -DGETCHAR -m64 -O3 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -DGETCHAR -O0 -g -xc++ %s -o %t && %run %t
+// RUN: %clangxx_msan -DGETCHAR -O3 -g -xc++ %s -o %t && %run %t
+// RUN: %clang_msan -DGETCHAR -O0 -g %s -o %t && %run %t
+// RUN: %clang_msan -DGETCHAR -O3 -g %s -o %t && %run %t
#include <assert.h>
#include <stdio.h>
diff --git a/test/msan/heap-origin.cc b/test/msan/heap-origin.cc
index 0920001be..4f170f0d7 100644
--- a/test/msan/heap-origin.cc
+++ b/test/msan/heap-origin.cc
@@ -1,19 +1,19 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O1 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
#include <stdlib.h>
diff --git a/test/msan/iconv.cc b/test/msan/iconv.cc
index ea6958b79..c4f253479 100644
--- a/test/msan/iconv.cc
+++ b/test/msan/iconv.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -g -DPOSITIVE %s -o %t && not %run %t |& FileCheck %s
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g -DPOSITIVE %s -o %t && not %run %t |& FileCheck %s
#include <assert.h>
#include <iconv.h>
diff --git a/test/msan/if_indextoname.cc b/test/msan/if_indextoname.cc
index b74aec16c..7f7dea7d5 100644
--- a/test/msan/if_indextoname.cc
+++ b/test/msan/if_indextoname.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t 2>&1
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t 2>&1
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t 2>&1
#include <assert.h>
#include <errno.h>
diff --git a/test/msan/ifaddrs.cc b/test/msan/ifaddrs.cc
index 6a0db3a5b..568e6615b 100644
--- a/test/msan/ifaddrs.cc
+++ b/test/msan/ifaddrs.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p 2>&1
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&1
#include <assert.h>
#include <errno.h>
diff --git a/test/msan/initgroups.cc b/test/msan/initgroups.cc
index 94f6cd825..d11fd582a 100644
--- a/test/msan/initgroups.cc
+++ b/test/msan/initgroups.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
#include <sys/types.h>
#include <grp.h>
diff --git a/test/msan/insertvalue_origin.cc b/test/msan/insertvalue_origin.cc
index 545debffa..a0c70023f 100644
--- a/test/msan/insertvalue_origin.cc
+++ b/test/msan/insertvalue_origin.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
// Test origin propagation through insertvalue IR instruction.
diff --git a/test/msan/ioctl.cc b/test/msan/ioctl.cc
index caa5c274f..e21ef636c 100644
--- a/test/msan/ioctl.cc
+++ b/test/msan/ioctl.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O3 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O3 -g %s -o %t && %run %t
#include <assert.h>
#include <stdlib.h>
diff --git a/test/msan/ioctl_custom.cc b/test/msan/ioctl_custom.cc
index 7c7fde4bd..6df22d75e 100644
--- a/test/msan/ioctl_custom.cc
+++ b/test/msan/ioctl_custom.cc
@@ -1,8 +1,8 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O3 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O3 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -DPOSITIVE -m64 -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_msan -DPOSITIVE -m64 -O3 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -DPOSITIVE -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -DPOSITIVE -O3 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
#include <assert.h>
#include <stdlib.h>
diff --git a/test/msan/ioctl_sound.cc b/test/msan/ioctl_sound.cc
index ed896f761..fb36c52f2 100644
--- a/test/msan/ioctl_sound.cc
+++ b/test/msan/ioctl_sound.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O3 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O3 -g %s -o %t && %run %t
#include <assert.h>
#include <fcntl.h>
diff --git a/test/msan/keep-going-dso.cc b/test/msan/keep-going-dso.cc
index 7975306c5..f32a513ea 100644
--- a/test/msan/keep-going-dso.cc
+++ b/test/msan/keep-going-dso.cc
@@ -1,15 +1,15 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
// FileCheck --check-prefix=CHECK-KEEP-GOING %s <%t.out
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
+// 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 -m64 -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
+// 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
-// RUN: %clangxx_msan -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// 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 -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
+// 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 -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
+// 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
diff --git a/test/msan/keep-going.cc b/test/msan/keep-going.cc
index 6426574a9..577297563 100644
--- a/test/msan/keep-going.cc
+++ b/test/msan/keep-going.cc
@@ -1,19 +1,19 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
// FileCheck %s <%t.out
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
+// 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 -m64 -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
+// 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 -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// 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 -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=0 not %run %t >%t.out 2>&1
+// 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 -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=keep_going=1 not %run %t >%t.out 2>&1
+// 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 -m64 -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 -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=halt_on_error=1 not %run %t >%t.out 2>&1
// FileCheck %s <%t.out
-// RUN: %clangxx_msan -m64 -mllvm -msan-keep-going=1 -O0 %s -o %t && MSAN_OPTIONS=halt_on_error=0 not %run %t >%t.out 2>&1
+// 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
// Test behaviour of -mllvm -msan-keep-going and MSAN_OPTIONS=keep_going.
diff --git a/test/msan/mallinfo.cc b/test/msan/mallinfo.cc
index 3f3086830..3c3692969 100644
--- a/test/msan/mallinfo.cc
+++ b/test/msan/mallinfo.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
#include <assert.h>
#include <malloc.h>
diff --git a/test/msan/mktime.cc b/test/msan/mktime.cc
index c419057c3..997fb0ddb 100644
--- a/test/msan/mktime.cc
+++ b/test/msan/mktime.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -g -DUNINIT %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g -DUNINIT %s -o %t && not %run %t 2>&1 | FileCheck %s
#include <assert.h>
#include <time.h>
diff --git a/test/msan/mmap_below_shadow.cc b/test/msan/mmap_below_shadow.cc
index 0b982d589..2b507d024 100644
--- a/test/msan/mmap_below_shadow.cc
+++ b/test/msan/mmap_below_shadow.cc
@@ -3,10 +3,10 @@
// Without MAP_FIXED, we ignore the address hint and map somewhere in
// application range.
-// RUN: %clangxx_msan -m64 -O0 -DFIXED=0 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -DFIXED=1 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -DFIXED=0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -DFIXED=1 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -DFIXED=0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -DFIXED=1 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -DFIXED=0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -DFIXED=1 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
#include <assert.h>
#include <errno.h>
diff --git a/test/msan/msan_check_mem_is_initialized.cc b/test/msan/msan_check_mem_is_initialized.cc
index 33558cd2f..599cf2d7d 100644
--- a/test/msan/msan_check_mem_is_initialized.cc
+++ b/test/msan/msan_check_mem_is_initialized.cc
@@ -1,9 +1,9 @@
-// RUN: %clangxx_msan -m64 -O0 -g -DPOSITIVE %s -o %t
+// RUN: %clangxx_msan -O0 -g -DPOSITIVE %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK
// RUN: MSAN_OPTIONS=verbosity=1 not %run %t 2>&1 | \
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VERBOSE
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
#include <sanitizer/msan_interface.h>
diff --git a/test/msan/msan_dump_shadow.cc b/test/msan/msan_dump_shadow.cc
index 08371e306..543fa7013 100644
--- a/test/msan/msan_dump_shadow.cc
+++ b/test/msan/msan_dump_shadow.cc
@@ -1,10 +1,10 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 -g %s -o %t && %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 -g %s -o %t && %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
#include <sanitizer/msan_interface.h>
diff --git a/test/msan/msan_print_shadow.cc b/test/msan/msan_print_shadow.cc
index f4894596a..9668be2c2 100644
--- a/test/msan/msan_print_shadow.cc
+++ b/test/msan/msan_print_shadow.cc
@@ -1,10 +1,10 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 -g %s -o %t && %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 -g %s -o %t && %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ORIGINS --check-prefix=CHECK-ORIGINS-2 < %t.out
#include <sanitizer/msan_interface.h>
diff --git a/test/msan/msan_print_shadow2.cc b/test/msan/msan_print_shadow2.cc
index 343ee9e5c..5095081c9 100644
--- a/test/msan/msan_print_shadow2.cc
+++ b/test/msan/msan_print_shadow2.cc
@@ -1,10 +1,10 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 -g %s -o %t && %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 -g %s -o %t && %run %t >%t.out 2>&1
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ORIGINS < %t.out
#include <sanitizer/msan_interface.h>
diff --git a/test/msan/msan_print_shadow3.cc b/test/msan/msan_print_shadow3.cc
index c605ef188..b29f3222d 100644
--- a/test/msan/msan_print_shadow3.cc
+++ b/test/msan/msan_print_shadow3.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
#include <stdint.h>
diff --git a/test/msan/mul_by_const.cc b/test/msan/mul_by_const.cc
index a975bb921..8240fdbed 100644
--- a/test/msan/mul_by_const.cc
+++ b/test/msan/mul_by_const.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && %run %t
+// RUN: %clangxx_msan -O2 %s -o %t && %run %t
#include <sanitizer/msan_interface.h>
diff --git a/test/msan/no_sanitize_memory.cc b/test/msan/no_sanitize_memory.cc
index c5643816c..5c53ee4f3 100644
--- a/test/msan/no_sanitize_memory.cc
+++ b/test/msan/no_sanitize_memory.cc
@@ -1,12 +1,12 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O0 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O1 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O2 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t -DCHECK_IN_F && %run %t >%t.out 2>&1
// Test that (no_sanitize_memory) functions
// * don't check shadow values (-DCHECK_IN_F)
diff --git a/test/msan/no_sanitize_memory_prop.cc b/test/msan/no_sanitize_memory_prop.cc
index 4275ebbf7..bfd4194dd 100644
--- a/test/msan/no_sanitize_memory_prop.cc
+++ b/test/msan/no_sanitize_memory_prop.cc
@@ -1,7 +1,7 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && %run %t >%t.out 2>&1
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t >%t.out 2>&1
// Test that (no_sanitize_memory) functions DO NOT propagate shadow.
diff --git a/test/msan/obstack.cc b/test/msan/obstack.cc
index 222f43b83..f1f53be4c 100644
--- a/test/msan/obstack.cc
+++ b/test/msan/obstack.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -g -DPOSITIVE %s -o %t && not %run %t |& FileCheck %s
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g -DPOSITIVE %s -o %t && not %run %t |& FileCheck %s
#include <obstack.h>
#include <sanitizer/msan_interface.h>
diff --git a/test/msan/origin-store-long.cc b/test/msan/origin-store-long.cc
index a7c2b7a7d..5c9fe04b7 100644
--- a/test/msan/origin-store-long.cc
+++ b/test/msan/origin-store-long.cc
@@ -1,7 +1,7 @@
// Check that 8-byte store updates origin for the full store range.
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
#include <sanitizer/msan_interface.h>
diff --git a/test/msan/param_tls_limit.cc b/test/msan/param_tls_limit.cc
index 869afc935..982ae1ebd 100644
--- a/test/msan/param_tls_limit.cc
+++ b/test/msan/param_tls_limit.cc
@@ -1,9 +1,9 @@
// ParamTLS has limited size. Everything that does not fit is considered fully
// initialized.
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && %run %t
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 %s -o %t && %run %t
#include <sanitizer/msan_interface.h>
#include <assert.h>
diff --git a/test/msan/print_stats.cc b/test/msan/print_stats.cc
index 74943835b..39af50417 100644
--- a/test/msan/print_stats.cc
+++ b/test/msan/print_stats.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -g %s -o %t
+// 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: MSAN_OPTIONS=print_stats=1 %run %t 2>&1 | \
@@ -6,13 +6,13 @@
// RUN: MSAN_OPTIONS=print_stats=1,atexit=1 %run %t 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-STATS %s
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -g -DPOSITIVE=1 %s -o %t
+// 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: MSAN_OPTIONS=print_stats=1 not %run %t 2>&1 | \
// RUN: FileCheck --check-prefix=CHECK --check-prefix=CHECK-STATS %s
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -g -DPOSITIVE=1 -mllvm -msan-keep-going=1 %s -o %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -g -DPOSITIVE=1 -mllvm -msan-keep-going=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: MSAN_OPTIONS=print_stats=1 not %run %t 2>&1 | \
diff --git a/test/msan/pthread_getattr_np_deadlock.cc b/test/msan/pthread_getattr_np_deadlock.cc
index 07f19cb61..0f5228085 100644
--- a/test/msan/pthread_getattr_np_deadlock.cc
+++ b/test/msan/pthread_getattr_np_deadlock.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -fsanitize-memory-track-origins -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && %run %t
// Regression test for a deadlock in pthread_getattr_np
diff --git a/test/msan/rand_r.cc b/test/msan/rand_r.cc
index d6bdb1dea..f40cf9f96 100644
--- a/test/msan/rand_r.cc
+++ b/test/msan/rand_r.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -g -DUNINIT %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g -DUNINIT %s -o %t && not %run %t 2>&1 | FileCheck %s
#include <assert.h>
#include <stdio.h>
diff --git a/test/msan/readdir64.cc b/test/msan/readdir64.cc
index 4f00d1838..e77ada6ac 100644
--- a/test/msan/readdir64.cc
+++ b/test/msan/readdir64.cc
@@ -1,12 +1,12 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O1 %s -o %t && %run %t
+// RUN: %clangxx_msan -O2 %s -o %t && %run %t
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O1 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O2 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
-// RUN: %clangxx_msan -m64 -O3 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
+// RUN: %clangxx_msan -O1 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
+// RUN: %clangxx_msan -O2 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
+// RUN: %clangxx_msan -O3 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t
// Test that readdir64 is intercepted as well as readdir.
diff --git a/test/msan/realloc-large-origin.cc b/test/msan/realloc-large-origin.cc
index de39394cb..ce25ad8c4 100644
--- a/test/msan/realloc-large-origin.cc
+++ b/test/msan/realloc-large-origin.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// 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: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
// This is a regression test: there used to be broken "stored to memory at"
diff --git a/test/msan/realloc-origin.cc b/test/msan/realloc-origin.cc
index 6707cc904..e6893713e 100644
--- a/test/msan/realloc-origin.cc
+++ b/test/msan/realloc-origin.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
// This test relies on realloc from 100 to 101 being done in-place.
diff --git a/test/msan/report-demangling.cc b/test/msan/report-demangling.cc
index e6d5c27ec..e75ba87ae 100644
--- a/test/msan/report-demangling.cc
+++ b/test/msan/report-demangling.cc
@@ -1,7 +1,7 @@
// Test that function name is mangled in the "created by an allocation" line,
// and demangled in the single-frame "stack trace" that follows.
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
__attribute__((noinline))
diff --git a/test/msan/scandir.cc b/test/msan/scandir.cc
index 571ba4f60..8adfe0066 100644
--- a/test/msan/scandir.cc
+++ b/test/msan/scandir.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p
#include <assert.h>
#include <glob.h>
diff --git a/test/msan/scandir_null.cc b/test/msan/scandir_null.cc
index e7663dc43..94ac31a41 100644
--- a/test/msan/scandir_null.cc
+++ b/test/msan/scandir_null.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p
-// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p
+// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p
#include <assert.h>
#include <glob.h>
diff --git a/test/msan/select.cc b/test/msan/select.cc
index 89de75eba..7b8c34785 100644
--- a/test/msan/select.cc
+++ b/test/msan/select.cc
@@ -1,10 +1,10 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
#include <stdlib.h>
diff --git a/test/msan/setlocale.cc b/test/msan/setlocale.cc
index b7007f78d..796f4454e 100644
--- a/test/msan/setlocale.cc
+++ b/test/msan/setlocale.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
#include <assert.h>
#include <locale.h>
diff --git a/test/msan/stack-origin.cc b/test/msan/stack-origin.cc
index c39c3a8cf..e69c07224 100644
--- a/test/msan/stack-origin.cc
+++ b/test/msan/stack-origin.cc
@@ -1,19 +1,19 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O1 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
#include <stdlib.h>
diff --git a/test/msan/stack-origin2.cc b/test/msan/stack-origin2.cc
index 0ba57607d..6c7428c2d 100644
--- a/test/msan/stack-origin2.cc
+++ b/test/msan/stack-origin2.cc
@@ -1,21 +1,21 @@
// Test that on the second entry to a function the origins are still right.
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O1 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
#include <stdlib.h>
diff --git a/test/msan/strlen_of_shadow.cc b/test/msan/strlen_of_shadow.cc
index 8f1b4e1fc..d6f8be70b 100644
--- a/test/msan/strlen_of_shadow.cc
+++ b/test/msan/strlen_of_shadow.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
// Check that strlen() and similar intercepted functions can be called on shadow
// memory.
diff --git a/test/msan/strxfrm.cc b/test/msan/strxfrm.cc
index b930a6af6..9a30d03c3 100644
--- a/test/msan/strxfrm.cc
+++ b/test/msan/strxfrm.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
#include <assert.h>
#include <sanitizer/msan_interface.h>
diff --git a/test/msan/sync_lock_set_and_test.cc b/test/msan/sync_lock_set_and_test.cc
index b6d344a61..11fd14fae 100644
--- a/test/msan/sync_lock_set_and_test.cc
+++ b/test/msan/sync_lock_set_and_test.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
int main(void) {
int i;
diff --git a/test/msan/textdomain.cc b/test/msan/textdomain.cc
index 47e991e8c..760debd68 100644
--- a/test/msan/textdomain.cc
+++ b/test/msan/textdomain.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
#include <libintl.h>
#include <stdio.h>
diff --git a/test/msan/times.cc b/test/msan/times.cc
index a042f548d..7c8188411 100644
--- a/test/msan/times.cc
+++ b/test/msan/times.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
#include <assert.h>
#include <stdlib.h>
diff --git a/test/msan/tls_reuse.cc b/test/msan/tls_reuse.cc
index e024a5a8d..78a328fa3 100644
--- a/test/msan/tls_reuse.cc
+++ b/test/msan/tls_reuse.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
// Check that when TLS block is reused between threads, its shadow is cleaned.
diff --git a/test/msan/tzset.cc b/test/msan/tzset.cc
index ed61d7bcc..05915e047 100644
--- a/test/msan/tzset.cc
+++ b/test/msan/tzset.cc
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
#include <stdlib.h>
#include <string.h>
diff --git a/test/msan/unaligned_read_origin.cc b/test/msan/unaligned_read_origin.cc
index e5618efbd..b04800a13 100644
--- a/test/msan/unaligned_read_origin.cc
+++ b/test/msan/unaligned_read_origin.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
#include <sanitizer/msan_interface.h>
diff --git a/test/msan/unpoison_string.cc b/test/msan/unpoison_string.cc
index ac947b9cf..84d952833 100644
--- a/test/msan/unpoison_string.cc
+++ b/test/msan/unpoison_string.cc
@@ -1,6 +1,6 @@
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t
// RUN: %run %t
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t
// RUN: %run %t
#include <assert.h>
diff --git a/test/msan/use-after-free.cc b/test/msan/use-after-free.cc
index 869bad98e..c50512447 100644
--- a/test/msan/use-after-free.cc
+++ b/test/msan/use-after-free.cc
@@ -1,19 +1,19 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O1 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O1 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O1 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
-// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
#include <stdlib.h>
diff --git a/test/msan/vector_cvt.cc b/test/msan/vector_cvt.cc
index bd9b6a8b8..d08ec3e3d 100644
--- a/test/msan/vector_cvt.cc
+++ b/test/msan/vector_cvt.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t
-// RUN: %clangxx_msan -DPOSITIVE -m64 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -DPOSITIVE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
#include <emmintrin.h>
diff --git a/test/msan/vector_select.cc b/test/msan/vector_select.cc
index afeb1ad50..4bfeba69c 100644
--- a/test/msan/vector_select.cc
+++ b/test/msan/vector_select.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_msan -m64 -O0 %s -c -o %t
-// RUN: %clangxx_msan -m64 -O3 %s -c -o %t
+// RUN: %clangxx_msan -O0 %s -c -o %t
+// RUN: %clangxx_msan -O3 %s -c -o %t
// Regression test for MemorySanitizer instrumentation of a select instruction
// with vector arguments.
diff --git a/test/sanitizer_common/CMakeLists.txt b/test/sanitizer_common/CMakeLists.txt
index 13eecbdc1..42f26902b 100644
--- a/test/sanitizer_common/CMakeLists.txt
+++ b/test/sanitizer_common/CMakeLists.txt
@@ -16,16 +16,26 @@ endif()
# Create a separate config for each tool we support.
foreach(tool ${SUPPORTED_TOOLS})
string(TOUPPER ${tool} tool_toupper)
- if(${tool_toupper}_SUPPORTED_ARCH)
+ if(${tool_toupper}_SUPPORTED_ARCH AND NOT COMPILER_RT_STANDALONE_BUILD)
+ list(APPEND SANITIZER_COMMON_TEST_DEPS ${tool})
+ endif()
+ foreach(arch ${${tool_toupper}_SUPPORTED_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)
+ endif()
+ set(CONFIG_NAME ${tool}-${arch}-${OS_NAME})
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
- ${CMAKE_CURRENT_BINARY_DIR}/${tool}/lit.site.cfg)
- list(APPEND SANITIZER_COMMON_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${tool})
- if(NOT COMPILER_RT_STANDALONE_BUILD)
- list(APPEND SANITIZER_COMMON_TEST_DEPS ${tool})
- endif()
- endif()
+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
+ list(APPEND SANITIZER_COMMON_TESTSUITES
+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+ endforeach()
endforeach()
# Unit tests.
diff --git a/test/sanitizer_common/TestCases/Linux/open_memstream.cc b/test/sanitizer_common/TestCases/Linux/open_memstream.cc
index 6abe0bfb1..69097c094 100644
--- a/test/sanitizer_common/TestCases/Linux/open_memstream.cc
+++ b/test/sanitizer_common/TestCases/Linux/open_memstream.cc
@@ -1,5 +1,6 @@
// RUN: %clangxx -m64 -O0 -g -xc++ %s -o %t && %run %t
// RUN: %clangxx -m64 -O3 -g -xc++ %s -o %t && %run %t
+// REQUIRES: x86_64-supported-target
#include <assert.h>
#include <stdio.h>
diff --git a/test/tsan/signal_segv_handler.cc b/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc
index 2d806eef6..9ea9fef70 100644
--- a/test/tsan/signal_segv_handler.cc
+++ b/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc
@@ -1,4 +1,4 @@
-// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" ASAN_OPTIONS="handle_segv=0 allow_user_segv_handler=1" %run %t 2>&1 | FileCheck %s
// JVM uses SEGV to preempt threads. All threads do a load from a known address
// periodically. When runtime needs to preempt threads, it unmaps the page.
@@ -13,7 +13,8 @@
// "benign" SEGVs that are handled by signal handler, and ensures that
// the process survive.
-#include "test.h"
+#include <stdio.h>
+#include <stdlib.h>
#include <signal.h>
#include <sys/mman.h>
@@ -24,15 +25,16 @@ void handler(int signo, siginfo_t *info, void *uctx) {
}
int main() {
- struct sigaction a;
+ struct sigaction a, old;
a.sa_sigaction = handler;
a.sa_flags = SA_SIGINFO;
- sigaction(SIGSEGV, &a, 0);
+ sigaction(SIGSEGV, &a, &old);
guard = mmap(0, 4096, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
for (int i = 0; i < 1000000; i++) {
mprotect(guard, 4096, PROT_NONE);
*(int*)guard = 1;
}
+ sigaction(SIGSEGV, &old, 0);
fprintf(stderr, "DONE\n");
}
diff --git a/test/sanitizer_common/lit.site.cfg.in b/test/sanitizer_common/lit.site.cfg.in
index 1e94aa567..64a3edf6c 100644
--- a/test/sanitizer_common/lit.site.cfg.in
+++ b/test/sanitizer_common/lit.site.cfg.in
@@ -3,6 +3,8 @@ lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configu
# Tool-specific config options.
config.tool_name = "@SANITIZER_COMMON_LIT_TEST_MODE@"
+config.target_cflags = "@SANITIZER_COMMON_TEST_TARGET_CFLAGS@"
+config.target_arch = "@SANITIZER_COMMON_TEST_TARGET_ARCH@"
# Load tool-specific config that would do the real work.
lit_config.load_config(config, "@SANITIZER_COMMON_LIT_SOURCE_DIR@/lit.common.cfg")
diff --git a/test/tsan/java_heap_init.cc b/test/tsan/java_heap_init.cc
new file mode 100644
index 000000000..bb7357c25
--- /dev/null
+++ b/test/tsan/java_heap_init.cc
@@ -0,0 +1,28 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+#include "java.h"
+#include <errno.h>
+#include <sys/mman.h>
+
+int main() {
+ // Test that munmap interceptor resets meta shadow for the memory range.
+ // Previously __tsan_java_move failed because it encountered non-zero meta
+ // shadow for the destination.
+ int const kHeapSize = 1024 * 1024;
+ jptr jheap = (jptr)mmap(0, kHeapSize, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (jheap == (jptr)MAP_FAILED)
+ return printf("mmap failed with %d\n", errno);
+ __atomic_store_n((int*)jheap, 1, __ATOMIC_RELEASE);
+ munmap((void*)jheap, kHeapSize);
+ jheap = (jptr)mmap((void*)jheap, kHeapSize, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (jheap == (jptr)MAP_FAILED)
+ return printf("second mmap failed with %d\n", errno);
+ __tsan_java_init(jheap, kHeapSize);
+ __tsan_java_move(jheap + 16, jheap, 16);
+ printf("DONE\n");
+ return __tsan_java_fini();
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
+// CHECK: DONE
diff --git a/test/tsan/mmap_large.cc b/test/tsan/mmap_large.cc
index 4ae4c0863..098530475 100644
--- a/test/tsan/mmap_large.cc
+++ b/test/tsan/mmap_large.cc
@@ -4,6 +4,13 @@
#include <errno.h>
#include <sys/mman.h>
+#if defined(__FreeBSD__)
+// The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
+// that, it was never implemented. So just define it to zero.
+#undef MAP_NORESERVE
+#define MAP_NORESERVE 0
+#endif
+
int main() {
#ifdef __x86_64__
const size_t kLog2Size = 39;
diff --git a/test/tsan/mmap_stress.cc b/test/tsan/mmap_stress.cc
new file mode 100644
index 000000000..5e3904adf
--- /dev/null
+++ b/test/tsan/mmap_stress.cc
@@ -0,0 +1,47 @@
+// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+#include "test.h"
+#include <errno.h>
+#include <sys/mman.h>
+
+void *SubWorker(void *arg) {
+ (void)arg;
+ const int kMmapSize = 65536;
+ for (int i = 0; i < 500; i++) {
+ int *ptr = (int*)mmap(0, kMmapSize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON, -1, 0);
+ *ptr = 42;
+ munmap(ptr, kMmapSize);
+ }
+ return 0;
+}
+
+void *Worker1(void *arg) {
+ (void)arg;
+ pthread_t th[4];
+ for (int i = 0; i < 4; i++)
+ pthread_create(&th[i], 0, SubWorker, 0);
+ for (int i = 0; i < 4; i++)
+ pthread_join(th[i], 0);
+ return 0;
+}
+
+void *Worker(void *arg) {
+ (void)arg;
+ pthread_t th[4];
+ for (int i = 0; i < 4; i++)
+ pthread_create(&th[i], 0, Worker1, 0);
+ for (int i = 0; i < 4; i++)
+ pthread_join(th[i], 0);
+ return 0;
+}
+
+int main() {
+ pthread_t th[4];
+ for (int i = 0; i < 4; i++)
+ pthread_create(&th[i], 0, Worker, 0);
+ for (int i = 0; i < 4; i++)
+ pthread_join(th[i], 0);
+ fprintf(stderr, "DONE\n");
+}
+
+// CHECK: DONE
diff --git a/test/tsan/test.h b/test/tsan/test.h
index bb861b077..4e877f6d8 100644
--- a/test/tsan/test.h
+++ b/test/tsan/test.h
@@ -11,10 +11,16 @@
__typeof(pthread_barrier_wait) *barrier_wait;
void barrier_init(pthread_barrier_t *barrier, unsigned count) {
+#if defined(__FreeBSD__)
+ static const char libpthread_name[] = "libpthread.so";
+#else
+ static const char libpthread_name[] = "libpthread.so.0";
+#endif
+
if (barrier_wait == 0) {
- void *h = dlopen("libpthread.so.0", RTLD_LAZY);
+ void *h = dlopen(libpthread_name, RTLD_LAZY);
if (h == 0) {
- fprintf(stderr, "failed to dlopen libpthread.so.0, exiting\n");
+ fprintf(stderr, "failed to dlopen %s, exiting\n", libpthread_name);
exit(1);
}
barrier_wait = (__typeof(barrier_wait))dlsym(h, "pthread_barrier_wait");
diff --git a/test/ubsan/TestCases/Integer/shift.cpp b/test/ubsan/TestCases/Integer/shift.cpp
index e86fac8d5..c8e01afcf 100644
--- a/test/ubsan/TestCases/Integer/shift.cpp
+++ b/test/ubsan/TestCases/Integer/shift.cpp
@@ -1,13 +1,20 @@
-// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-LSH_OVERFLOW
-// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<=' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-LSH_OVERFLOW
-// RUN: %clangxx -DTOO_LOW -DOP='<<' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
-// RUN: %clangxx -DTOO_LOW -DOP='>>' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
-// RUN: %clangxx -DTOO_LOW -DOP='<<=' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
-// RUN: %clangxx -DTOO_LOW -DOP='>>=' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
-// RUN: %clangxx -DTOO_HIGH -DOP='<<' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
-// RUN: %clangxx -DTOO_HIGH -DOP='>>' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
-// RUN: %clangxx -DTOO_HIGH -DOP='<<=' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
-// RUN: %clangxx -DTOO_HIGH -DOP='>>=' -fsanitize=shift %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
+// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-LSH_OVERFLOW
+// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-LSH_OVERFLOW
+// RUN: %clangxx -DTOO_LOW -DOP='<<' -fsanitize=shift-exponent -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
+// RUN: %clangxx -DTOO_LOW -DOP='>>' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
+// RUN: %clangxx -DTOO_LOW -DOP='<<=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
+// RUN: %clangxx -DTOO_LOW -DOP='>>=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_LOW
+// RUN: %clangxx -DTOO_HIGH -DOP='<<' -fsanitize=shift-exponent -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
+// RUN: %clangxx -DTOO_HIGH -DOP='>>' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
+// RUN: %clangxx -DTOO_HIGH -DOP='<<=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
+// RUN: %clangxx -DTOO_HIGH -DOP='>>=' -fsanitize=shift -fno-sanitize-recover=shift %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TOO_HIGH
+
+// RUN: %clangxx -DLSH_OVERFLOW -DOP='<<' -fsanitize=shift-exponent -fno-sanitize-recover=shift %s -o %t && %run %t
+// RUN: %clangxx -DLSH_OVERFLOW -DOP='>>' -fsanitize=shift-exponent -fno-sanitize-recover=shift %s -o %t && %run %t
+// RUN: %clangxx -DTOO_LOW -DOP='<<' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t && %run %t
+// RUN: %clangxx -DTOO_LOW -DOP='>>' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t && %run %t
+// RUN: %clangxx -DTOO_HIGH -DOP='<<' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t && %run %t
+// RUN: %clangxx -DTOO_HIGH -DOP='>>' -fsanitize=shift-base -fno-sanitize-recover=shift %s -o %t && %run %t
#include <stdint.h>
@@ -20,18 +27,19 @@ int main() {
b <<= 1; // still ok, unsigned
#ifdef LSH_OVERFLOW
- // CHECK-LSH_OVERFLOW: shift.cpp:24:5: runtime error: left shift of negative value -2147483648
+ // CHECK-LSH_OVERFLOW: shift.cpp:[[@LINE+1]]:5: runtime error: left shift of negative value -2147483648
a OP 1;
#endif
#ifdef TOO_LOW
- // CHECK-TOO_LOW: shift.cpp:29:5: runtime error: shift exponent -3 is negative
+ a = 0;
+ // CHECK-TOO_LOW: shift.cpp:[[@LINE+1]]:5: runtime error: shift exponent -3 is negative
a OP (-3);
#endif
#ifdef TOO_HIGH
a = 0;
- // CHECK-TOO_HIGH: shift.cpp:35:5: runtime error: shift exponent 32 is too large for 32-bit type 'int'
+ // CHECK-TOO_HIGH: shift.cpp:[[@LINE+1]]:5: runtime error: shift exponent 32 is too large for 32-bit type 'int'
a OP 32;
#endif
}
diff --git a/test/ubsan/TestCases/Integer/summary.cpp b/test/ubsan/TestCases/Integer/summary.cpp
index 6e9aec63c..21f537b92 100644
--- a/test/ubsan/TestCases/Integer/summary.cpp
+++ b/test/ubsan/TestCases/Integer/summary.cpp
@@ -5,6 +5,6 @@
int main() {
(void)(uint64_t(10000000000000000000ull) + uint64_t(9000000000000000000ull));
- // CHECK: SUMMARY: AddressSanitizer: undefined-behavior {{.*}}summary.cpp:[[@LINE-1]]
+ // CHECK: SUMMARY: AddressSanitizer: undefined-behavior {{.*}}summary.cpp:[[@LINE-1]]:44
return 0;
}
diff --git a/test/ubsan/TestCases/Misc/coverage-levels.cc b/test/ubsan/TestCases/Misc/Linux/coverage-levels.cc
index 2fe12ffef..02521722f 100644
--- a/test/ubsan/TestCases/Misc/coverage-levels.cc
+++ b/test/ubsan/TestCases/Misc/Linux/coverage-levels.cc
@@ -14,8 +14,6 @@
// RUN: %clangxx -fsanitize=shift -O1 -fsanitize-coverage=3 %s -o %t
// RUN: UBSAN_OPTIONS=$OPT ASAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 --check-prefix=CHECK_WARN
-// XFAIL: darwin
-
volatile int sink;
int main(int argc, char **argv) {
int shift = argc * 32;
diff --git a/test/ubsan/TestCases/Misc/Linux/lit.local.cfg b/test/ubsan/TestCases/Misc/Linux/lit.local.cfg
new file mode 100644
index 000000000..57271b807
--- /dev/null
+++ b/test/ubsan/TestCases/Misc/Linux/lit.local.cfg
@@ -0,0 +1,9 @@
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+if root.host_os not in ['Linux']:
+ config.unsupported = True
diff --git a/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp b/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp
index 806e45c7d..a77680efd 100644
--- a/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp
+++ b/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp
@@ -1,9 +1,6 @@
// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
-// FIXME: This test produces linker errors on Darwin.
-// XFAIL: darwin
-
struct S { virtual int f() { return 0; } };
struct T : virtual S {};