From 3157f602e565eb73f5a1ae3105d52e8ffa6e41c0 Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Mon, 22 Aug 2016 23:21:25 +0200 Subject: [PATCH] Imported Upstream version 1.11.0+dfsg1 --- CONTRIBUTING.md | 11 +- Makefile.in | 21 +- README.md | 69 +- configure | 408 ++-- mk/cfg/i686-unknown-linux-gnu.mk | 2 +- mk/cfg/i686-unknown-linux-musl.mk | 2 +- mk/cfg/mips-unknown-linux-gnu.mk | 6 +- mk/cfg/x86_64-unknown-linux-musl.mk | 2 +- mk/crates.mk | 46 +- mk/llvm.mk | 27 +- mk/main.mk | 18 +- mk/rt.mk | 161 +- mk/tests.mk | 1 + src/bootstrap/README.md | 2 +- src/bootstrap/bootstrap.py | 63 +- src/bootstrap/build/cc.rs | 5 +- src/bootstrap/build/check.rs | 128 +- src/bootstrap/build/clean.rs | 3 + src/bootstrap/build/config.rs | 18 +- src/bootstrap/build/dist.rs | 4 +- src/bootstrap/build/mod.rs | 32 +- src/bootstrap/build/native.rs | 85 +- src/bootstrap/build/sanity.rs | 8 +- src/bootstrap/build/step.rs | 118 +- src/bootstrap/mk/Makefile.in | 5 + src/build_helper/lib.rs | 12 +- src/compiler-rt/CMakeLists.txt | 6 + .../cmake/Modules/AddCompilerRT.cmake | 35 +- .../cmake/Modules/CompilerRTCompile.cmake | 13 - .../cmake/Modules/CompilerRTDarwinUtils.cmake | 287 ++- .../cmake/Modules/CompilerRTUtils.cmake | 2 +- src/compiler-rt/cmake/config-ix.cmake | 258 ++- .../include/sanitizer/common_interface_defs.h | 6 +- .../include/sanitizer/coverage_interface.h | 7 + src/compiler-rt/lib/CMakeLists.txt | 6 +- src/compiler-rt/lib/asan/.clang-format | 1 + src/compiler-rt/lib/asan/README.txt | 2 +- src/compiler-rt/lib/asan/asan_activation.cc | 5 - src/compiler-rt/lib/asan/asan_flags.cc | 8 - src/compiler-rt/lib/asan/asan_flags.inc | 15 +- src/compiler-rt/lib/asan/asan_interceptors.cc | 4 +- .../lib/asan/asan_interface_internal.h | 13 + src/compiler-rt/lib/asan/asan_internal.h | 2 - src/compiler-rt/lib/asan/asan_linux.cc | 8 - src/compiler-rt/lib/asan/asan_mac.cc | 181 +- src/compiler-rt/lib/asan/asan_malloc_linux.cc | 21 +- src/compiler-rt/lib/asan/asan_malloc_mac.cc | 4 - src/compiler-rt/lib/asan/asan_mapping.h | 6 +- src/compiler-rt/lib/asan/asan_new_delete.cc | 2 +- src/compiler-rt/lib/asan/asan_poisoning.cc | 4 +- src/compiler-rt/lib/asan/asan_posix.cc | 2 + src/compiler-rt/lib/asan/asan_report.cc | 211 +- src/compiler-rt/lib/asan/asan_report.h | 68 +- src/compiler-rt/lib/asan/asan_rtl.cc | 81 +- src/compiler-rt/lib/asan/asan_win.cc | 8 - .../lib/asan/asan_win_dll_thunk.cc | 9 +- .../asan/asan_win_dynamic_runtime_thunk.cc | 1 + .../lib/asan/scripts/asan_device_setup | 9 +- .../lib/asan/scripts/asan_symbolize.py | 2 +- .../lib/asan/tests/asan_mac_test.cc | 4 +- .../lib/asan/tests/asan_noinst_test.cc | 2 +- src/compiler-rt/lib/asan/tests/asan_test.cc | 8 +- .../lib/asan/tests/asan_test_main.cc | 3 +- src/compiler-rt/lib/builtins/CMakeLists.txt | 94 +- .../builtins/Darwin-excludes/ios-armv7.txt | 52 +- .../builtins/Darwin-excludes/ios-armv7s.txt | 52 +- src/compiler-rt/lib/builtins/arm/adddf3vfp.S | 3 + src/compiler-rt/lib/builtins/arm/addsf3vfp.S | 3 + .../lib/builtins/arm/aeabi_cdcmp.S | 2 + .../lib/builtins/arm/aeabi_cfcmp.S | 2 + src/compiler-rt/lib/builtins/arm/aeabi_dcmp.S | 3 + src/compiler-rt/lib/builtins/arm/aeabi_fcmp.S | 3 + .../lib/builtins/arm/aeabi_idivmod.S | 3 + .../lib/builtins/arm/aeabi_ldivmod.S | 3 + .../lib/builtins/arm/aeabi_memcmp.S | 3 + .../lib/builtins/arm/aeabi_memcpy.S | 3 + .../lib/builtins/arm/aeabi_memmove.S | 3 + .../lib/builtins/arm/aeabi_memset.S | 2 + .../lib/builtins/arm/aeabi_uidivmod.S | 3 + .../lib/builtins/arm/aeabi_uldivmod.S | 3 + src/compiler-rt/lib/builtins/arm/bswapdi2.S | 3 + src/compiler-rt/lib/builtins/arm/bswapsi2.S | 3 + src/compiler-rt/lib/builtins/arm/clzdi2.S | 3 + src/compiler-rt/lib/builtins/arm/clzsi2.S | 3 + src/compiler-rt/lib/builtins/arm/comparesf2.S | 3 + src/compiler-rt/lib/builtins/arm/divdf3vfp.S | 3 + src/compiler-rt/lib/builtins/arm/divmodsi4.S | 3 + src/compiler-rt/lib/builtins/arm/divsf3vfp.S | 3 + src/compiler-rt/lib/builtins/arm/divsi3.S | 3 + src/compiler-rt/lib/builtins/arm/eqdf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/eqsf2vfp.S | 3 + .../lib/builtins/arm/extendsfdf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/fixdfsivfp.S | 3 + src/compiler-rt/lib/builtins/arm/fixsfsivfp.S | 3 + .../lib/builtins/arm/fixunsdfsivfp.S | 3 + .../lib/builtins/arm/fixunssfsivfp.S | 3 + .../lib/builtins/arm/floatsidfvfp.S | 3 + .../lib/builtins/arm/floatsisfvfp.S | 3 + .../lib/builtins/arm/floatunssidfvfp.S | 3 + .../lib/builtins/arm/floatunssisfvfp.S | 3 + src/compiler-rt/lib/builtins/arm/gedf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/gesf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/gtdf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/gtsf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/ledf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/lesf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/ltdf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/ltsf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/modsi3.S | 3 + src/compiler-rt/lib/builtins/arm/muldf3vfp.S | 3 + src/compiler-rt/lib/builtins/arm/mulsf3vfp.S | 3 + src/compiler-rt/lib/builtins/arm/nedf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/negdf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/negsf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/nesf2vfp.S | 3 + .../builtins/arm/restore_vfp_d8_d15_regs.S | 2 + .../lib/builtins/arm/save_vfp_d8_d15_regs.S | 2 + src/compiler-rt/lib/builtins/arm/subdf3vfp.S | 3 + src/compiler-rt/lib/builtins/arm/subsf3vfp.S | 3 + src/compiler-rt/lib/builtins/arm/switch16.S | 2 + src/compiler-rt/lib/builtins/arm/switch32.S | 2 + src/compiler-rt/lib/builtins/arm/switch8.S | 2 + src/compiler-rt/lib/builtins/arm/switchu8.S | 2 + .../lib/builtins/arm/sync_fetch_and_add_4.S | 2 + .../lib/builtins/arm/sync_fetch_and_add_8.S | 2 + .../lib/builtins/arm/sync_fetch_and_and_4.S | 3 + .../lib/builtins/arm/sync_fetch_and_and_8.S | 3 + .../lib/builtins/arm/sync_fetch_and_max_4.S | 2 + .../lib/builtins/arm/sync_fetch_and_max_8.S | 3 + .../lib/builtins/arm/sync_fetch_and_min_4.S | 2 + .../lib/builtins/arm/sync_fetch_and_min_8.S | 3 + .../lib/builtins/arm/sync_fetch_and_nand_4.S | 2 + .../lib/builtins/arm/sync_fetch_and_nand_8.S | 2 + .../lib/builtins/arm/sync_fetch_and_or_4.S | 2 + .../lib/builtins/arm/sync_fetch_and_or_8.S | 2 + .../lib/builtins/arm/sync_fetch_and_sub_4.S | 2 + .../lib/builtins/arm/sync_fetch_and_sub_8.S | 2 + .../lib/builtins/arm/sync_fetch_and_umax_4.S | 2 + .../lib/builtins/arm/sync_fetch_and_umax_8.S | 3 + .../lib/builtins/arm/sync_fetch_and_umin_4.S | 2 + .../lib/builtins/arm/sync_fetch_and_umin_8.S | 3 + .../lib/builtins/arm/sync_fetch_and_xor_4.S | 2 + .../lib/builtins/arm/sync_fetch_and_xor_8.S | 2 + .../lib/builtins/arm/sync_synchronize.S | 3 + .../lib/builtins/arm/truncdfsf2vfp.S | 3 + src/compiler-rt/lib/builtins/arm/udivmodsi4.S | 3 + src/compiler-rt/lib/builtins/arm/udivsi3.S | 3 + src/compiler-rt/lib/builtins/arm/umodsi3.S | 3 + .../lib/builtins/arm/unorddf2vfp.S | 3 + .../lib/builtins/arm/unordsf2vfp.S | 3 + src/compiler-rt/lib/builtins/assembly.h | 10 + src/compiler-rt/lib/builtins/divtc3.c | 60 + .../lib/builtins/gcc_personality_v0.c | 45 +- src/compiler-rt/lib/builtins/i386/ashldi3.S | 3 + src/compiler-rt/lib/builtins/i386/ashrdi3.S | 3 + src/compiler-rt/lib/builtins/i386/divdi3.S | 3 + src/compiler-rt/lib/builtins/i386/floatdidf.S | 3 + src/compiler-rt/lib/builtins/i386/floatdisf.S | 3 + src/compiler-rt/lib/builtins/i386/floatdixf.S | 3 + .../lib/builtins/i386/floatundidf.S | 3 + .../lib/builtins/i386/floatundisf.S | 3 + .../lib/builtins/i386/floatundixf.S | 3 + src/compiler-rt/lib/builtins/i386/lshrdi3.S | 3 + src/compiler-rt/lib/builtins/i386/moddi3.S | 3 + src/compiler-rt/lib/builtins/i386/muldi3.S | 3 + src/compiler-rt/lib/builtins/i386/udivdi3.S | 3 + src/compiler-rt/lib/builtins/i386/umoddi3.S | 3 + src/compiler-rt/lib/builtins/int_endianness.h | 13 - src/compiler-rt/lib/builtins/int_lib.h | 2 +- src/compiler-rt/lib/builtins/int_types.h | 7 +- src/compiler-rt/lib/builtins/ppc/DD.h | 13 +- src/compiler-rt/lib/builtins/ppc/divtc3.c | 5 - src/compiler-rt/lib/builtins/ppc/multc3.c | 4 - src/compiler-rt/lib/builtins/ppc/restFP.S | 3 + src/compiler-rt/lib/builtins/ppc/saveFP.S | 3 + .../lib/builtins/x86_64/floatundidf.S | 3 + .../lib/builtins/x86_64/floatundisf.S | 3 + .../lib/builtins/x86_64/floatundixf.S | 3 + src/compiler-rt/lib/cfi/CMakeLists.txt | 36 + src/compiler-rt/lib/cfi/cfi.cc | 271 +++ src/compiler-rt/lib/dfsan/.clang-format | 1 + src/compiler-rt/lib/dfsan/dfsan.cc | 59 +- src/compiler-rt/lib/dfsan/dfsan.h | 13 +- src/compiler-rt/lib/dfsan/dfsan_platform.h | 107 + .../lib/interception/.clang-format | 1 + src/compiler-rt/lib/lsan/.clang-format | 1 + src/compiler-rt/lib/lsan/lsan_common.cc | 4 +- src/compiler-rt/lib/msan/.clang-format | 1 + src/compiler-rt/lib/msan/msan.cc | 2 +- src/compiler-rt/lib/msan/msan_interceptors.cc | 13 +- src/compiler-rt/lib/msan/tests/msan_test.cc | 16 +- src/compiler-rt/lib/profile/CMakeLists.txt | 44 +- src/compiler-rt/lib/profile/GCDAProfiling.c | 6 + src/compiler-rt/lib/profile/InstrProfData.inc | 767 +++++++ src/compiler-rt/lib/profile/InstrProfiling.c | 77 +- src/compiler-rt/lib/profile/InstrProfiling.h | 81 +- .../lib/profile/InstrProfilingBuffer.c | 80 +- .../lib/profile/InstrProfilingFile.c | 111 +- .../lib/profile/InstrProfilingInternal.h | 78 + .../profile/InstrProfilingPlatformDarwin.c | 45 +- .../lib/profile/InstrProfilingPlatformLinux.c | 59 +- .../lib/profile/InstrProfilingPlatformOther.c | 46 +- .../lib/profile/InstrProfilingPort.h | 62 + .../lib/profile/InstrProfilingRuntime.cc | 3 +- .../lib/profile/InstrProfilingUtil.c | 3 +- .../lib/profile/InstrProfilingValue.c | 180 ++ .../lib/profile/InstrProfilingWriter.c | 175 ++ src/compiler-rt/lib/profile/WindowsMMap.c | 128 ++ src/compiler-rt/lib/profile/WindowsMMap.h | 65 + src/compiler-rt/lib/safestack/.clang-format | 1 + src/compiler-rt/lib/safestack/safestack.cc | 7 +- .../lib/sanitizer_common/.clang-format | 1 + .../lib/sanitizer_common/sanitizer_asm.h | 20 +- .../lib/sanitizer_common/sanitizer_common.cc | 43 +- .../lib/sanitizer_common/sanitizer_common.h | 36 +- .../sanitizer_common_interceptors.inc | 367 +-- .../sanitizer_common_libcdep.cc | 24 +- .../sanitizer_common_nolibc.cc | 5 +- .../sanitizer_coverage_libcdep.cc | 40 +- .../lib/sanitizer_common/sanitizer_flags.inc | 10 +- .../sanitizer_internal_defs.h | 5 +- .../lib/sanitizer_common/sanitizer_libc.cc | 24 + .../lib/sanitizer_common/sanitizer_libc.h | 2 + .../lib/sanitizer_common/sanitizer_linux.cc | 104 +- .../lib/sanitizer_common/sanitizer_linux.h | 3 +- .../sanitizer_linux_libcdep.cc | 65 +- .../lib/sanitizer_common/sanitizer_mac.cc | 277 ++- .../lib/sanitizer_common/sanitizer_mac.h | 14 + .../sanitizer_common/sanitizer_malloc_mac.inc | 43 +- .../lib/sanitizer_common/sanitizer_platform.h | 29 +- .../sanitizer_platform_interceptors.h | 2 + .../sanitizer_platform_limits_posix.cc | 17 +- .../lib/sanitizer_common/sanitizer_posix.cc | 20 +- .../lib/sanitizer_common/sanitizer_posix.h | 1 + .../sanitizer_posix_libcdep.cc | 3 +- .../lib/sanitizer_common/sanitizer_printf.cc | 7 +- .../sanitizer_procmaps_linux.cc | 2 +- .../sanitizer_procmaps_mac.cc | 2 +- .../sanitizer_common/sanitizer_stacktrace.cc | 2 +- .../sanitizer_common/sanitizer_stacktrace.h | 2 +- .../sanitizer_stoptheworld_linux_libcdep.cc | 6 +- .../sanitizer_suppressions.cc | 2 +- .../sanitizer_common/sanitizer_suppressions.h | 3 +- .../sanitizer_symbolizer_mac.cc | 73 +- .../sanitizer_symbolizer_posix_libcdep.cc | 6 +- .../sanitizer_tls_get_addr.cc | 11 +- .../lib/sanitizer_common/sanitizer_win.cc | 17 +- .../tests/sanitizer_common_test.cc | 24 + .../tests/sanitizer_libc_test.cc | 56 + .../tests/sanitizer_stacktrace_test.cc | 2 +- src/compiler-rt/lib/tsan/.clang-format | 1 + src/compiler-rt/lib/tsan/CMakeLists.txt | 70 +- src/compiler-rt/lib/tsan/Makefile.old | 109 - src/compiler-rt/lib/tsan/analyze_libtsan.sh | 23 +- src/compiler-rt/lib/tsan/check_analyze.sh | 20 +- src/compiler-rt/lib/tsan/check_memcpy.sh | 31 - src/compiler-rt/lib/tsan/go/buildgo.sh | 30 +- src/compiler-rt/lib/tsan/rtl/Makefile.old | 63 - src/compiler-rt/lib/tsan/rtl/tsan_defs.h | 3 - .../lib/tsan/rtl/tsan_dense_alloc.h | 2 +- src/compiler-rt/lib/tsan/rtl/tsan_flags.cc | 14 +- .../lib/tsan/rtl/tsan_interceptors.cc | 201 +- .../lib/tsan/rtl/tsan_interceptors.h | 20 + .../lib/tsan/rtl/tsan_interceptors_mac.cc | 91 + .../lib/tsan/rtl/tsan_libdispatch_mac.cc | 284 +++ .../lib/tsan/rtl/tsan_malloc_mac.cc | 32 +- src/compiler-rt/lib/tsan/rtl/tsan_mman.cc | 6 +- .../lib/tsan/rtl/tsan_new_delete.cc | 4 +- src/compiler-rt/lib/tsan/rtl/tsan_platform.h | 780 +++++-- .../lib/tsan/rtl/tsan_platform_linux.cc | 46 +- .../lib/tsan/rtl/tsan_platform_mac.cc | 21 +- .../lib/tsan/rtl/tsan_platform_posix.cc | 69 +- .../lib/tsan/rtl/tsan_platform_windows.cc | 3 + src/compiler-rt/lib/tsan/rtl/tsan_ppc_regs.h | 96 + src/compiler-rt/lib/tsan/rtl/tsan_report.cc | 32 +- src/compiler-rt/lib/tsan/rtl/tsan_rtl.cc | 22 +- src/compiler-rt/lib/tsan/rtl/tsan_rtl.h | 7 +- .../lib/tsan/rtl/tsan_rtl_aarch64.S | 206 ++ src/compiler-rt/lib/tsan/rtl/tsan_rtl_amd64.S | 99 +- src/compiler-rt/lib/tsan/rtl/tsan_rtl_ppc64.S | 288 +++ .../lib/tsan/rtl/tsan_rtl_report.cc | 26 +- .../lib/tsan/rtl/tsan_suppressions.cc | 7 +- .../lib/tsan/rtl/tsan_symbolize.cc | 10 +- src/compiler-rt/lib/tsan/tests/CMakeLists.txt | 50 +- .../lib/tsan/tests/rtl/CMakeLists.txt | 4 +- .../lib/tsan/tests/rtl/tsan_posix.cc | 15 +- .../lib/tsan/tests/rtl/tsan_test.cc | 7 + .../lib/tsan/tests/rtl/tsan_test_util.h | 10 +- ..._util_linux.cc => tsan_test_util_posix.cc} | 113 +- .../lib/tsan/tests/unit/tsan_clock_test.cc | 7 +- .../lib/tsan/tests/unit/tsan_mman_test.cc | 4 +- src/compiler-rt/lib/ubsan/ubsan_checks.inc | 56 +- src/compiler-rt/lib/ubsan/ubsan_diag.cc | 46 +- src/compiler-rt/lib/ubsan/ubsan_diag.h | 21 +- src/compiler-rt/lib/ubsan/ubsan_handlers.cc | 216 +- .../lib/ubsan/ubsan_handlers_cxx.cc | 29 +- src/compiler-rt/make/config.mk | 4 +- src/compiler-rt/make/platform/clang_darwin.mk | 567 +++++ .../make/platform/clang_darwin_test_input.c | 15 + src/compiler-rt/make/platform/clang_linux.mk | 91 + .../make/platform/clang_linux_test_input.c | 4 + .../make/platform/clang_macho_embedded.mk | 297 +++ .../clang_macho_embedded_test_input.c | 0 src/compiler-rt/make/platform/clang_mingw.mk | 30 + src/compiler-rt/make/platform/darwin_bni.mk | 135 ++ src/compiler-rt/make/platform/multi_arch.mk | 15 + src/compiler-rt/make/platform/triple.mk | 78 - src/compiler-rt/test/CMakeLists.txt | 4 +- .../Darwin/atos-symbolizer-dyld-root-path.cc | 9 +- .../TestCases/Darwin/crashlog-stacktraces.c | 5 + .../Darwin/dyld_insert_libraries_reexec.cc | 4 +- .../Darwin/interface_symbols_darwin.c | 12 + .../asan/TestCases/Linux/calloc-preload.c | 36 + .../TestCases/Linux/interface_symbols_linux.c | 12 + .../test/asan/TestCases/Linux/mincore.cc | 34 + .../test/asan/TestCases/Linux/static_tls.cc | 2 +- .../TestCases/Posix/halt_on_error-signals.c | 102 + .../TestCases/Posix/halt_on_error-torture.cc | 87 + .../Posix/halt_on_error_suppress_equal_pcs.cc | 55 + .../asan/TestCases/alloca_vla_interact.cc | 1 - .../test/asan/TestCases/coverage-pc-buffer.cc | 48 + .../test/asan/TestCases/coverage-reset.cc | 1 + .../test/asan/TestCases/halt_on_error-1.c | 29 + .../test/asan/TestCases/speculative_load2.cc | 24 + .../test/asan/TestCases/throw_catch.cc | 3 - src/compiler-rt/test/asan/lit.cfg | 2 + .../test/builtins/Unit/divtc3_test.c | 13 +- src/compiler-rt/test/cfi/CMakeLists.txt | 3 + .../test/cfi/base-derived-destructor.cpp | 2 +- .../cfi/cross-dso/icall/icall-from-dso.cpp | 26 + .../test/cfi/cross-dso/icall/icall.cpp | 21 + .../test/cfi/cross-dso/icall/lit.local.cfg | 3 + .../test/cfi/cross-dso/lit.local.cfg | 9 + .../test/cfi/cross-dso/simple-fail.cpp | 92 + .../test/cfi/cross-dso/simple-pass.cpp | 65 + src/compiler-rt/test/cfi/lit.cfg | 5 +- ...tructor.cc => cleanup_in_tsd_destructor.c} | 2 +- .../test/lsan/TestCases/disabler.c | 24 + .../test/lsan/TestCases/disabler.cc | 10 +- ...ructor.cc => disabler_in_tsd_destructor.c} | 5 +- .../{ignore_object.cc => ignore_object.c} | 4 +- src/compiler-rt/test/msan/ctermid.cc | 13 + .../test/msan/dlopen_executable.cc | 17 + src/compiler-rt/test/msan/fork.cc | 5 + .../test/msan/insertvalue_origin.cc | 1 - .../test/msan/signal_stress_test.cc | 3 - .../profile/Inputs/instrprof-shared-lib.c | 9 + .../profile/Inputs/instrprof-shared-main.c | 13 + .../test/profile/Linux/instrprof-basic.c | 31 + .../test/profile/Linux/instrprof-dlopen.test | 34 + .../Linux/instrprof-dynamic-one-shared.test | 23 + .../Linux/instrprof-dynamic-two-shared.test | 24 + .../test/profile/Linux/lit.local.cfg | 37 + .../test/profile/instrprof-bufferio.c | 128 ++ .../test/profile/instrprof-error.c | 12 + .../test/profile/instrprof-shared.test | 75 + .../test/profile/instrprof-value-prof-2.c | 135 ++ .../test/profile/instrprof-value-prof.c | 225 ++ .../test/profile/instrprof-version-mismatch.c | 11 + .../test/profile/instrprof-without-libc.c | 6 + src/compiler-rt/test/safestack/lit.cfg | 5 + src/compiler-rt/test/safestack/overflow.c | 6 + .../TestCases/Linux/closedir.c | 5 + .../sanitizer_common/TestCases/Linux/ill.cc | 27 + .../TestCases/fopen_nullptr.c | 6 + src/compiler-rt/test/tsan/CMakeLists.txt | 38 +- .../test/tsan/Darwin/gcd-async-norace.mm | 26 + .../test/tsan/Darwin/gcd-async-race.mm | 38 + .../test/tsan/Darwin/gcd-groups-norace.mm | 53 + .../test/tsan/Darwin/gcd-groups-stress.mm | 43 + src/compiler-rt/test/tsan/Darwin/gcd-once.mm | 55 + .../test/tsan/Darwin/gcd-semaphore-norace.mm | 29 + .../tsan/Darwin/gcd-serial-queue-norace.mm | 40 + .../test/tsan/Darwin/gcd-sync-norace.mm | 32 + .../test/tsan/Darwin/gcd-sync-race.mm | 44 + .../test/tsan/Darwin/lit.local.cfg | 9 + src/compiler-rt/test/tsan/Darwin/objc-race.mm | 55 + .../test/tsan/Darwin/objc-simple.mm | 13 + .../test/tsan/Darwin/osspinlock-norace.cc | 30 + .../test/tsan/Darwin/symbolizer-atos.cc | 26 + .../test/tsan/Darwin/symbolizer-dladdr.cc | 27 + .../test/tsan/Linux/check_memcpy.cc | 15 + .../test/tsan/allocator_returns_null.cc | 10 +- src/compiler-rt/test/tsan/barrier.cc | 3 + .../test/tsan/bench_acquire_only.cc | 3 + .../test/tsan/bench_acquire_release.cc | 3 + .../test/tsan/bench_local_mutex.cc | 3 + src/compiler-rt/test/tsan/bench_mutex.cc | 3 + .../test/tsan/bench_release_only.cc | 3 + src/compiler-rt/test/tsan/bench_rwmutex.cc | 3 + .../test/tsan/bench_single_writer.cc | 3 + .../test/tsan/bench_ten_mutexes.cc | 3 + src/compiler-rt/test/tsan/cond_cancel.c | 8 + src/compiler-rt/test/tsan/cond_version.c | 3 + .../tsan/deadlock_detector_stress_test.cc | 20 +- src/compiler-rt/test/tsan/dl_iterate_phdr.cc | 3 +- src/compiler-rt/test/tsan/dlclose.cc | 4 +- src/compiler-rt/test/tsan/fd_tid_recycled.cc | 54 + src/compiler-rt/test/tsan/fork_atexit.cc | 3 +- src/compiler-rt/test/tsan/fork_deadlock.cc | 3 +- .../test/tsan/fork_multithreaded.cc | 3 +- .../test/tsan/fork_multithreaded3.cc | 1 + src/compiler-rt/test/tsan/free_race.c | 2 +- src/compiler-rt/test/tsan/getline_nohang.cc | 2 +- src/compiler-rt/test/tsan/global_race.cc | 6 +- src/compiler-rt/test/tsan/global_race2.cc | 6 +- src/compiler-rt/test/tsan/global_race3.cc | 6 +- src/compiler-rt/test/tsan/halt_on_error.cc | 2 +- src/compiler-rt/test/tsan/ignore_lib0.cc | 4 +- src/compiler-rt/test/tsan/ignore_lib1.cc | 2 +- src/compiler-rt/test/tsan/ignore_lib2.cc | 2 +- src/compiler-rt/test/tsan/ignore_lib3.cc | 2 +- .../test/tsan/inlined_memcpy_race.cc | 2 +- src/compiler-rt/test/tsan/java_race_pc.cc | 4 + src/compiler-rt/test/tsan/lit.cfg | 25 +- src/compiler-rt/test/tsan/lit.site.cfg.in | 3 + src/compiler-rt/test/tsan/load_shared_lib.cc | 2 +- src/compiler-rt/test/tsan/longjmp.cc | 3 +- src/compiler-rt/test/tsan/longjmp2.cc | 3 +- src/compiler-rt/test/tsan/longjmp3.cc | 3 +- src/compiler-rt/test/tsan/longjmp4.cc | 3 +- src/compiler-rt/test/tsan/malloc_overflow.cc | 2 +- src/compiler-rt/test/tsan/map32bit.cc | 6 +- src/compiler-rt/test/tsan/memcmp_race.cc | 4 +- src/compiler-rt/test/tsan/memcpy_race.cc | 6 +- src/compiler-rt/test/tsan/mmap_large.cc | 4 +- src/compiler-rt/test/tsan/mmap_stress.cc | 41 +- src/compiler-rt/test/tsan/mop_with_offset.cc | 4 +- src/compiler-rt/test/tsan/mop_with_offset2.cc | 4 +- src/compiler-rt/test/tsan/mutex_cycle2.c | 8 +- src/compiler-rt/test/tsan/mutexset1.cc | 2 +- src/compiler-rt/test/tsan/mutexset2.cc | 2 +- src/compiler-rt/test/tsan/mutexset3.cc | 4 +- src/compiler-rt/test/tsan/mutexset4.cc | 4 +- src/compiler-rt/test/tsan/mutexset5.cc | 4 +- src/compiler-rt/test/tsan/mutexset6.cc | 16 +- src/compiler-rt/test/tsan/mutexset8.cc | 2 +- src/compiler-rt/test/tsan/pie_test.cc | 12 + src/compiler-rt/test/tsan/printf-1.c | 4 +- .../test/tsan/pthread_atfork_deadlock.c | 2 +- src/compiler-rt/test/tsan/race_on_barrier.c | 4 + src/compiler-rt/test/tsan/race_on_barrier2.c | 4 + src/compiler-rt/test/tsan/race_on_heap.cc | 3 +- src/compiler-rt/test/tsan/race_on_mutex.c | 7 +- .../test/tsan/race_on_speculative_load.cc | 2 +- .../test/tsan/race_top_suppression.cc | 2 +- .../test/tsan/race_top_suppression1.cc | 2 +- .../real_deadlock_detector_stress_test.cc | 7 +- src/compiler-rt/test/tsan/setuid2.c | 12 +- src/compiler-rt/test/tsan/signal_cond.cc | 14 +- src/compiler-rt/test/tsan/signal_errno.cc | 4 + src/compiler-rt/test/tsan/signal_longjmp.cc | 17 +- src/compiler-rt/test/tsan/signal_recursive.cc | 2 +- src/compiler-rt/test/tsan/signal_reset.cc | 1 + src/compiler-rt/test/tsan/signal_sync.cc | 1 + src/compiler-rt/test/tsan/signal_thread.cc | 1 + src/compiler-rt/test/tsan/stack_sync_reuse.cc | 8 +- .../test/tsan/suppressions_global.cc | 2 +- .../test/tsan/suppressions_race.cc | 2 +- .../test/tsan/suppressions_race2.cc | 2 +- src/compiler-rt/test/tsan/test.h | 82 +- src/compiler-rt/test/tsan/test_output.sh | 66 - src/compiler-rt/test/tsan/thread_name2.cc | 3 + src/compiler-rt/test/tsan/tls_race.cc | 6 +- src/compiler-rt/test/tsan/tls_race2.cc | 7 +- src/compiler-rt/test/tsan/vfork.cc | 1 + .../tsan/virtual_inheritance_compile_bug.cc | 2 +- src/compiler-rt/test/tsan/vptr_benign_race.cc | 20 +- .../test/ubsan/TestCases/Integer/summary.cpp | 2 +- .../ubsan/TestCases/Integer/suppressions.cpp | 33 + .../TestCases/Misc/Linux/ubsan_options.cc | 2 +- src/compiler-rt/test/ubsan/lit.common.cfg | 1 + src/doc/book/advanced-linking.md | 2 +- src/doc/book/choosing-your-guarantees.md | 2 +- src/doc/book/closures.md | 10 +- src/doc/book/compiler-plugins.md | 7 +- src/doc/book/crates-and-modules.md | 7 +- src/doc/book/documentation.md | 2 +- src/doc/book/error-handling.md | 26 +- src/doc/book/functions.md | 10 +- src/doc/book/glossary.md | 6 + src/doc/book/guessing-game.md | 2 +- src/doc/book/lifetimes.md | 10 +- src/doc/book/loops.md | 2 +- src/doc/book/no-stdlib.md | 26 +- src/doc/book/ownership.md | 10 +- src/doc/book/patterns.md | 2 +- src/doc/book/primitive-types.md | 4 +- src/doc/book/references-and-borrowing.md | 46 +- src/doc/book/slice-patterns.md | 6 +- src/doc/book/strings.md | 2 +- src/doc/book/testing.md | 16 +- src/doc/book/traits.md | 4 +- ...using-rust-without-the-standard-library.md | 9 +- src/doc/book/variable-bindings.md | 18 +- src/doc/book/vectors.md | 6 +- src/doc/footer.inc | 2 +- src/doc/nomicon/README.md | 2 +- src/doc/nomicon/safe-unsafe-meaning.md | 251 +-- src/doc/reference.md | 25 +- src/doc/rust.css | 2 +- src/doc/rustc-ux-guidelines.md | 14 +- src/etc/Dockerfile | 33 + src/etc/debugger_pretty_printers_common.py | 2 +- src/etc/gdb_rust_pretty_printing.py | 17 +- src/etc/get-stage0.py | 17 +- src/etc/htmldocck.py | 1 + src/etc/rust-lldb | 11 + src/jemalloc/src/zone.c | 34 +- src/liballoc/arc.rs | 22 +- src/liballoc/boxed.rs | 5 +- src/liballoc/boxed_test.rs | 2 +- src/liballoc/heap.rs | 2 +- src/liballoc/raw_vec.rs | 6 +- src/liballoc/rc.rs | 10 +- src/liballoc_jemalloc/build.rs | 32 +- src/liballoc_jemalloc/lib.rs | 11 +- src/libcollections/binary_heap.rs | 74 +- src/libcollections/borrow.rs | 11 + src/libcollections/btree/map.rs | 669 ++++-- src/libcollections/btree/node.rs | 294 ++- src/libcollections/btree/set.rs | 38 +- src/libcollections/fmt.rs | 10 +- src/libcollections/lib.rs | 4 +- src/libcollections/str.rs | 275 +-- src/libcollections/vec.rs | 4 +- src/libcollectionstest/binary_heap.rs | 18 + src/libcollectionstest/btree/map.rs | 166 +- src/libcollectionstest/btree/mod.rs | 30 + src/libcollectionstest/btree/set.rs | 48 + src/libcollectionstest/enum_set.rs | 18 +- src/libcollectionstest/lib.rs | 5 +- src/libcollectionstest/linked_list.rs | 45 +- src/libcollectionstest/slice.rs | 364 ++- src/libcollectionstest/str.rs | 88 +- src/libcollectionstest/string.rs | 117 +- src/libcollectionstest/vec.rs | 56 +- src/libcollectionstest/vec_deque.rs | 129 +- src/libcore/Cargo.toml | 1 - src/libcore/any.rs | 2 +- src/libcore/cell.rs | 83 +- src/libcore/char.rs | 78 +- src/libcore/clone.rs | 32 +- src/libcore/cmp.rs | 168 +- src/libcore/default.rs | 138 +- src/libcore/fmt/mod.rs | 15 +- src/libcore/fmt/num.rs | 4 + src/libcore/hash/mod.rs | 33 +- src/libcore/hash/sip.rs | 249 ++- src/libcore/intrinsics.rs | 12 +- src/libcore/iter/iterator.rs | 67 +- src/libcore/iter/mod.rs | 194 +- src/libcore/iter/range.rs | 169 +- src/libcore/iter/traits.rs | 101 + src/libcore/iter_private.rs | 27 + src/libcore/lib.rs | 4 +- src/libcore/macros.rs | 13 +- src/libcore/marker.rs | 39 +- src/libcore/mem.rs | 11 + src/libcore/num/dec2flt/algorithm.rs | 2 +- src/libcore/num/dec2flt/mod.rs | 14 +- src/libcore/num/dec2flt/rawfp.rs | 35 +- src/libcore/num/f32.rs | 8 +- src/libcore/num/f64.rs | 8 +- src/libcore/num/flt2dec/decoder.rs | 9 +- src/libcore/num/int_macros.rs | 18 - src/libcore/num/isize.rs | 2 + src/libcore/num/mod.rs | 103 +- src/libcore/num/uint_macros.rs | 13 - src/libcore/num/usize.rs | 2 + src/libcore/num/wrapping.rs | 6 + src/libcore/ops.rs | 48 +- src/libcore/raw.rs | 76 - src/libcore/result.rs | 5 +- src/libcore/slice.rs | 29 +- src/libcore/str/mod.rs | 160 +- src/libcore/str/pattern.rs | 8 +- src/libcore/sync/atomic.rs | 34 +- src/libcoretest/cell.rs | 32 - src/libcoretest/char.rs | 6 + src/libcoretest/hash/sip.rs | 131 +- src/libcoretest/iter.rs | 31 + src/libcoretest/lib.rs | 3 +- src/libcoretest/mem.rs | 14 + src/libcoretest/num/dec2flt/rawfp.rs | 23 +- src/libcoretest/num/flt2dec/estimator.rs | 3 +- src/libcoretest/num/flt2dec/mod.rs | 39 +- src/libflate/lib.rs | 10 +- src/liblibc/libc-test/build.rs | 1 + src/liblibc/src/unix/bsd/apple/mod.rs | 12 + src/liblibc/src/unix/bsd/freebsdlike/mod.rs | 11 + .../src/unix/bsd/openbsdlike/bitrig.rs | 5 + src/liblibc/src/unix/bsd/openbsdlike/mod.rs | 4 + .../src/unix/bsd/openbsdlike/netbsd.rs | 3 + .../src/unix/bsd/openbsdlike/openbsd.rs | 5 + src/liblibc/src/unix/mod.rs | 10 + src/liblibc/src/unix/notbsd/android/b32.rs | 19 + src/liblibc/src/unix/notbsd/android/b64.rs | 19 + src/liblibc/src/unix/notbsd/android/mod.rs | 17 + src/liblibc/src/unix/notbsd/linux/mips.rs | 18 + src/liblibc/src/unix/notbsd/linux/mod.rs | 3 + .../src/unix/notbsd/linux/musl/b32/arm.rs | 61 +- .../src/unix/notbsd/linux/musl/b32/asmjs.rs | 61 +- .../src/unix/notbsd/linux/musl/b32/mips.rs | 61 +- .../src/unix/notbsd/linux/musl/b32/x86.rs | 61 +- .../src/unix/notbsd/linux/musl/b64/mod.rs | 61 +- src/liblibc/src/unix/notbsd/linux/musl/mod.rs | 21 +- .../src/unix/notbsd/linux/other/b32/mod.rs | 17 + .../src/unix/notbsd/linux/other/b64/mod.rs | 17 + .../src/unix/notbsd/linux/other/mod.rs | 11 + src/liblibc/src/unix/notbsd/mod.rs | 4 + src/liblibc/src/unix/solaris/mod.rs | 7 + src/liblog/lib.rs | 6 +- src/libpanic_abort/lib.rs | 5 +- src/libpanic_unwind/dwarf/eh.rs | 75 +- src/libpanic_unwind/dwarf/mod.rs | 30 +- src/libpanic_unwind/gcc.rs | 166 +- src/libpanic_unwind/lib.rs | 16 +- src/libpanic_unwind/seh.rs | 19 +- src/libpanic_unwind/seh64_gnu.rs | 41 +- src/libpanic_unwind/windows.rs | 12 +- src/librand/chacha.rs | 8 +- src/librand/distributions/exponential.rs | 6 +- src/librand/distributions/gamma.rs | 8 +- src/librand/distributions/mod.rs | 10 +- src/librand/distributions/normal.rs | 8 +- src/librand/distributions/range.rs | 4 +- src/librand/isaac.rs | 16 +- src/librand/lib.rs | 10 +- src/librand/rand_impls.rs | 5 +- src/librand/reseeding.rs | 11 +- src/librustc/Cargo.toml | 2 + src/librustc/cfg/construct.rs | 16 +- src/librustc/dep_graph/dep_node.rs | 19 +- src/librustc/dep_graph/query.rs | 24 +- src/librustc/dep_graph/raii.rs | 8 +- src/librustc/dep_graph/thread.rs | 2 - src/librustc/dep_graph/visit.rs | 2 +- src/librustc/diagnostics.rs | 262 ++- src/librustc/hir/check_attr.rs | 2 +- src/librustc/hir/def.rs | 24 +- src/librustc/hir/fold.rs | 35 +- src/librustc/hir/intravisit.rs | 105 +- src/librustc/hir/lowering.rs | 352 ++- src/librustc/hir/map/blocks.rs | 9 +- src/librustc/hir/map/collector.rs | 4 +- src/librustc/hir/map/def_collector.rs | 35 +- src/librustc/hir/map/definitions.rs | 8 +- src/librustc/hir/map/mod.rs | 18 +- src/librustc/hir/mod.rs | 62 +- src/librustc/hir/pat_util.rs | 125 +- src/librustc/hir/print.rs | 133 +- src/librustc/infer/combine.rs | 8 +- src/librustc/infer/error_reporting.rs | 59 +- src/librustc/infer/freshen.rs | 9 +- src/librustc/infer/higher_ranked/mod.rs | 311 ++- src/librustc/infer/mod.rs | 141 +- .../infer/region_inference/graphviz.rs | 8 +- src/librustc/infer/region_inference/mod.rs | 665 +++--- src/librustc/infer/type_variable.rs | 17 +- src/librustc/lib.rs | 6 +- src/librustc/lint/builtin.rs | 9 +- src/librustc/lint/context.rs | 40 +- src/librustc/lint/mod.rs | 5 +- src/librustc/middle/astconv_util.rs | 10 +- src/librustc/middle/const_val.rs | 53 +- src/librustc/middle/cstore.rs | 13 +- src/librustc/middle/dataflow.rs | 9 +- src/librustc/middle/dead.rs | 88 +- src/librustc/middle/dependency_format.rs | 15 +- src/librustc/middle/effect.rs | 4 +- src/librustc/middle/entry.rs | 2 +- src/librustc/middle/expr_use_visitor.rs | 215 +- src/librustc/middle/intrinsicck.rs | 4 +- src/librustc/middle/lang_items.rs | 4 +- src/librustc/middle/liveness.rs | 36 +- src/librustc/middle/mem_categorization.rs | 228 +- src/librustc/middle/reachable.rs | 8 +- src/librustc/middle/region.rs | 19 +- src/librustc/middle/resolve_lifetime.rs | 308 ++- src/librustc/middle/stability.rs | 50 +- src/librustc/middle/weak_lang_items.rs | 7 +- src/librustc/mir/cache.rs | 69 + src/librustc/mir/repr.rs | 442 ++-- src/librustc/mir/tcx.rs | 28 +- src/librustc/mir/transform.rs | 75 +- .../mir}/traversal.rs | 25 +- src/librustc/mir/visit.rs | 151 +- src/librustc/session/config.rs | 27 +- src/librustc/session/mod.rs | 70 +- src/librustc/traits/coherence.rs | 2 +- src/librustc/traits/error_reporting.rs | 7 +- src/librustc/traits/fulfill.rs | 10 +- src/librustc/traits/mod.rs | 12 +- src/librustc/traits/project.rs | 386 +++- src/librustc/traits/select.rs | 32 +- src/librustc/traits/specialize/mod.rs | 84 +- src/librustc/traits/util.rs | 2 +- src/librustc/ty/adjustment.rs | 5 +- src/librustc/ty/contents.rs | 11 +- src/librustc/ty/context.rs | 10 +- src/librustc/ty/error.rs | 4 +- src/librustc/ty/flags.rs | 8 +- src/librustc/ty/fold.rs | 28 +- src/librustc/ty/item_path.rs | 40 +- src/librustc/ty/layout.rs | 24 +- src/librustc/ty/mod.rs | 130 +- src/librustc/ty/structural_impls.rs | 2 +- src/librustc/ty/sty.rs | 33 +- src/librustc/ty/subst.rs | 4 +- src/librustc/ty/util.rs | 25 +- src/librustc/ty/wf.rs | 2 +- src/librustc/util/common.rs | 12 + src/librustc/util/ppaux.rs | 111 +- src/librustc_bitflags/lib.rs | 4 +- src/librustc_borrowck/Cargo.toml | 3 + src/librustc_borrowck/bitslice.rs | 82 +- src/librustc_borrowck/borrowck/check_loans.rs | 2 +- src/librustc_borrowck/borrowck/fragments.rs | 2 +- .../borrowck/gather_loans/gather_moves.rs | 19 +- .../borrowck/gather_loans/lifetime.rs | 2 +- .../borrowck/gather_loans/mod.rs | 5 +- .../borrowck/gather_loans/move_error.rs | 8 +- .../borrowck/gather_loans/restrictions.rs | 2 +- .../borrowck/mir/abs_domain.rs | 2 + .../borrowck/mir/dataflow.rs | 504 ----- .../borrowck/mir/dataflow/graphviz.rs | 344 +++ .../borrowck/mir/dataflow/impls.rs | 572 +++++ .../borrowck/mir/dataflow/mod.rs | 507 +++++ .../borrowck/mir/dataflow/sanity_check.rs | 171 ++ .../borrowck/mir/elaborate_drops.rs | 1034 +++++++++ .../borrowck/mir/gather_moves.rs | 246 +- .../borrowck/mir/graphviz.rs | 232 -- src/librustc_borrowck/borrowck/mir/mod.rs | 334 ++- src/librustc_borrowck/borrowck/mir/patch.rs | 179 ++ src/librustc_borrowck/borrowck/mod.rs | 12 +- src/librustc_borrowck/borrowck/move_data.rs | 9 +- src/librustc_borrowck/diagnostics.rs | 107 +- src/librustc_borrowck/indexed_set.rs | 159 ++ src/librustc_borrowck/lib.rs | 6 +- src/librustc_const_eval/Cargo.toml | 1 + src/librustc_const_eval/check_match.rs | 505 +++-- src/librustc_const_eval/diagnostics.rs | 11 +- src/librustc_const_eval/eval.rs | 224 +- src/librustc_const_eval/lib.rs | 3 +- src/librustc_const_math/err.rs | 22 +- src/librustc_const_math/float.rs | 173 ++ src/librustc_const_math/int.rs | 39 + src/librustc_const_math/is.rs | 15 +- src/librustc_const_math/lib.rs | 2 + src/librustc_const_math/us.rs | 15 +- src/librustc_data_structures/bitvec.rs | 18 +- .../control_flow_graph/dominators/mod.rs | 284 +++ .../control_flow_graph/dominators/test.rs | 57 + .../control_flow_graph/iterate/mod.rs | 70 + .../control_flow_graph/iterate/test.rs | 55 + .../control_flow_graph/mod.rs | 45 + .../control_flow_graph/reachable/mod.rs | 65 + .../control_flow_graph/reachable/test.rs | 64 + .../control_flow_graph/reference.rs | 43 + .../control_flow_graph/test.rs | 78 + .../control_flow_graph/transpose.rs | 59 + src/librustc_data_structures/indexed_vec.rs | 242 ++ src/librustc_data_structures/lib.rs | 3 + .../snapshot_map/mod.rs | 138 ++ .../snapshot_map/test.rs | 50 + src/librustc_data_structures/tuple_slice.rs | 26 +- src/librustc_driver/Cargo.toml | 2 + src/librustc_driver/driver.rs | 428 ++-- src/librustc_driver/lib.rs | 31 +- src/librustc_driver/pretty.rs | 16 +- src/librustc_driver/test.rs | 28 +- src/librustc_errors/Cargo.toml | 14 + .../errors => librustc_errors}/emitter.rs | 322 +-- .../errors/mod.rs => librustc_errors/lib.rs} | 85 +- .../registry.rs | 0 .../mod.rs => librustc_errors/snippet.rs} | 68 +- src/librustc_incremental/Cargo.toml | 1 + src/librustc_incremental/assert_dep_graph.rs | 82 +- src/librustc_incremental/calculate_svh.rs | 8 +- src/librustc_incremental/lib.rs | 1 + src/librustc_incremental/persist/directory.rs | 4 +- src/librustc_incremental/persist/hash.rs | 4 +- src/librustc_incremental/persist/load.rs | 12 +- src/librustc_incremental/persist/save.rs | 8 +- src/librustc_lint/Cargo.toml | 1 + src/librustc_lint/bad_style.rs | 19 +- src/librustc_lint/builtin.rs | 41 +- src/librustc_lint/lib.rs | 7 +- src/librustc_lint/types.rs | 10 +- src/librustc_lint/unused.rs | 22 +- src/librustc_llvm/archive_ro.rs | 29 +- src/librustc_llvm/build.rs | 59 +- src/librustc_llvm/diagnostic.rs | 49 +- src/librustc_llvm/lib.rs | 15 + src/librustc_metadata/Cargo.toml | 3 + src/librustc_metadata/astencode.rs | 71 +- src/librustc_metadata/common.rs | 2 +- src/librustc_metadata/creader.rs | 154 +- src/librustc_metadata/csearch.rs | 21 +- src/librustc_metadata/cstore.rs | 63 +- src/librustc_metadata/decoder.rs | 142 +- src/librustc_metadata/encoder.rs | 74 +- src/librustc_metadata/lib.rs | 4 +- src/librustc_metadata/loader.rs | 20 +- src/librustc_metadata/macro_import.rs | 77 +- src/librustc_metadata/tydecode.rs | 43 +- src/librustc_metadata/tyencode.rs | 35 +- src/librustc_mir/Cargo.toml | 1 + src/librustc_mir/build/block.rs | 43 +- src/librustc_mir/build/cfg.rs | 36 +- src/librustc_mir/build/expr/as_lvalue.rs | 27 +- src/librustc_mir/build/expr/as_operand.rs | 2 +- src/librustc_mir/build/expr/as_rvalue.rs | 179 +- src/librustc_mir/build/expr/as_temp.rs | 6 +- src/librustc_mir/build/expr/into.rs | 53 +- src/librustc_mir/build/expr/stmt.rs | 49 +- src/librustc_mir/build/matches/mod.rs | 261 ++- src/librustc_mir/build/matches/simplify.rs | 43 +- src/librustc_mir/build/matches/test.rs | 299 ++- src/librustc_mir/build/matches/util.rs | 73 +- src/librustc_mir/build/misc.rs | 71 +- src/librustc_mir/build/mod.rs | 148 +- src/librustc_mir/build/scope.rs | 308 ++- src/librustc_mir/graphviz.rs | 16 +- src/librustc_mir/hair/cx/expr.rs | 39 +- src/librustc_mir/hair/cx/mod.rs | 47 +- src/librustc_mir/hair/cx/pattern.rs | 84 +- src/librustc_mir/hair/mod.rs | 2 +- src/librustc_mir/lib.rs | 2 +- src/librustc_mir/mir_map.rs | 18 +- src/librustc_mir/pretty.rs | 203 +- src/librustc_mir/transform/add_call_guards.rs | 82 + .../transform/break_cleanup_edges.rs | 111 - src/librustc_mir/transform/dump_mir.rs | 73 + src/librustc_mir/transform/mod.rs | 5 +- src/librustc_mir/transform/no_landing_pads.rs | 7 +- src/librustc_mir/transform/promote_consts.rs | 135 +- src/librustc_mir/transform/qualify_consts.rs | 144 +- .../transform/remove_dead_blocks.rs | 86 - .../transform/simplify_branches.rs | 66 + src/librustc_mir/transform/simplify_cfg.rs | 338 +-- src/librustc_mir/transform/type_check.rs | 187 +- src/librustc_passes/Cargo.toml | 2 + src/librustc_passes/ast_validation.rs | 171 ++ src/librustc_passes/consts.rs | 26 +- src/librustc_passes/diagnostics.rs | 67 +- src/librustc_passes/lib.rs | 3 + src/librustc_passes/loops.rs | 2 +- src/librustc_passes/no_asm.rs | 2 +- src/librustc_passes/rvalues.rs | 2 +- src/librustc_passes/static_recursion.rs | 2 +- src/librustc_plugin/Cargo.toml | 3 +- src/librustc_plugin/build.rs | 4 +- src/librustc_plugin/lib.rs | 3 +- src/librustc_plugin/load.rs | 5 +- src/librustc_plugin/registry.rs | 2 +- src/librustc_privacy/Cargo.toml | 2 +- src/librustc_privacy/diagnostics.rs | 56 +- src/librustc_privacy/lib.rs | 145 +- src/librustc_resolve/Cargo.toml | 2 + src/librustc_resolve/build_reduced_graph.rs | 76 +- src/librustc_resolve/check_unused.rs | 4 +- src/librustc_resolve/diagnostics.rs | 488 ++-- src/librustc_resolve/lib.rs | 1038 ++++----- src/librustc_resolve/resolve_imports.rs | 28 +- src/librustc_save_analysis/Cargo.toml | 1 + src/librustc_save_analysis/data.rs | 21 +- src/librustc_save_analysis/dump_visitor.rs | 118 +- src/librustc_save_analysis/external_data.rs | 23 +- src/librustc_save_analysis/json_dumper.rs | 47 +- src/librustc_save_analysis/lib.rs | 57 +- src/librustc_save_analysis/span_utils.rs | 4 +- src/librustc_trans/Cargo.toml | 3 +- src/librustc_trans/_match.rs | 267 ++- src/librustc_trans/adt.rs | 5 +- src/librustc_trans/attributes.rs | 24 +- src/librustc_trans/back/archive.rs | 256 +-- src/librustc_trans/back/link.rs | 66 +- src/librustc_trans/back/linker.rs | 116 +- src/librustc_trans/back/msvc/arch.rs | 56 + src/librustc_trans/back/msvc/mod.rs | 353 +-- src/librustc_trans/back/symbol_names.rs | 167 +- src/librustc_trans/back/write.rs | 22 +- src/librustc_trans/base.rs | 218 +- src/librustc_trans/build.rs | 2 +- src/librustc_trans/builder.rs | 2 +- src/librustc_trans/callee.rs | 59 +- src/librustc_trans/closure.rs | 10 +- src/librustc_trans/collector.rs | 26 +- src/librustc_trans/common.rs | 109 +- src/librustc_trans/consts.rs | 66 +- src/librustc_trans/context.rs | 60 +- src/librustc_trans/controlflow.rs | 8 +- src/librustc_trans/datum.rs | 2 +- .../debuginfo/create_scope_map.rs | 179 +- src/librustc_trans/debuginfo/metadata.rs | 47 +- src/librustc_trans/debuginfo/mod.rs | 25 +- src/librustc_trans/debuginfo/namespace.rs | 4 +- src/librustc_trans/debuginfo/source_loc.rs | 6 +- src/librustc_trans/debuginfo/utils.rs | 10 +- src/librustc_trans/diagnostics.rs | 4 +- src/librustc_trans/expr.rs | 47 +- src/librustc_trans/glue.rs | 16 +- src/librustc_trans/intrinsic.rs | 4 +- src/librustc_trans/lib.rs | 5 +- src/librustc_trans/meth.rs | 6 +- src/librustc_trans/mir/analyze.rs | 255 ++- src/librustc_trans/mir/block.rs | 600 +++-- src/librustc_trans/mir/constant.rs | 393 ++-- src/librustc_trans/mir/drop.rs | 27 - src/librustc_trans/mir/lvalue.rs | 190 +- src/librustc_trans/mir/mod.rs | 246 +- src/librustc_trans/mir/operand.rs | 203 +- src/librustc_trans/mir/rvalue.rs | 229 +- src/librustc_trans/mir/statement.rs | 60 +- src/librustc_trans/monomorphize.rs | 20 +- src/librustc_trans/partitioning.rs | 11 + src/librustc_trans/symbol_names_test.rs | 3 +- src/librustc_trans/type_.rs | 1 + src/librustc_typeck/Cargo.toml | 2 + src/librustc_typeck/astconv.rs | 72 +- src/librustc_typeck/check/_match.rs | 297 ++- src/librustc_typeck/check/assoc.rs | 2 +- src/librustc_typeck/check/autoderef.rs | 210 ++ src/librustc_typeck/check/callee.rs | 22 +- src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/check/coercion.rs | 34 +- src/librustc_typeck/check/compare_method.rs | 121 +- src/librustc_typeck/check/demand.rs | 2 +- src/librustc_typeck/check/dropck.rs | 8 +- src/librustc_typeck/check/intrinsic.rs | 3 +- src/librustc_typeck/check/method/confirm.rs | 102 +- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 63 +- src/librustc_typeck/check/method/suggest.rs | 69 +- src/librustc_typeck/check/mod.rs | 464 ++-- src/librustc_typeck/check/regionck.rs | 20 +- src/librustc_typeck/check/upvar.rs | 92 +- src/librustc_typeck/check/wfcheck.rs | 5 +- src/librustc_typeck/check/writeback.rs | 20 +- src/librustc_typeck/check_unused.rs | 2 +- src/librustc_typeck/coherence/mod.rs | 11 +- src/librustc_typeck/coherence/orphan.rs | 2 +- src/librustc_typeck/collect.rs | 49 +- src/librustc_typeck/diagnostics.rs | 360 ++- src/librustc_typeck/lib.rs | 22 +- src/librustc_typeck/rscope.rs | 2 +- src/librustc_typeck/variance/constraints.rs | 4 +- src/librustc_unicode/char.rs | 42 +- src/librustc_unicode/lib.rs | 8 +- src/librustc_unicode/u_str.rs | 4 +- src/librustdoc/Cargo.toml | 2 + src/librustdoc/clean/inline.rs | 24 +- src/librustdoc/clean/mod.rs | 36 +- src/librustdoc/core.rs | 25 +- src/librustdoc/doctree.rs | 8 +- src/librustdoc/html/format.rs | 41 +- src/librustdoc/html/highlight.rs | 14 +- src/librustdoc/html/markdown.rs | 55 +- src/librustdoc/html/render.rs | 254 ++- src/librustdoc/html/static/main.js | 7 +- src/librustdoc/html/static/rustdoc.css | 31 +- src/librustdoc/html/static/styles/main.css | 9 +- src/librustdoc/lib.rs | 2 + src/librustdoc/passes.rs | 58 +- src/librustdoc/test.rs | 67 +- src/librustdoc/visit_ast.rs | 16 +- src/libserialize/json.rs | 10 +- src/libstd/build.rs | 3 +- src/libstd/collections/hash/map.rs | 41 +- src/libstd/collections/hash/table.rs | 345 +-- src/libstd/collections/mod.rs | 6 +- src/libstd/error.rs | 7 + src/libstd/ffi/c_str.rs | 32 + src/libstd/fs.rs | 20 +- src/libstd/io/cursor.rs | 2 + src/libstd/io/util.rs | 29 +- src/libstd/lib.rs | 23 +- src/libstd/macros.rs | 2 +- src/libstd/net/addr.rs | 10 +- src/libstd/net/ip.rs | 57 +- src/libstd/net/mod.rs | 9 +- src/libstd/num/f32.rs | 81 +- src/libstd/num/f64.rs | 75 +- src/libstd/num/mod.rs | 7 +- src/libstd/os/android/raw.rs | 3 +- src/libstd/os/bitrig/raw.rs | 3 +- src/libstd/os/dragonfly/raw.rs | 3 +- src/libstd/os/emscripten/raw.rs | 3 +- src/libstd/os/freebsd/raw.rs | 3 +- src/libstd/os/ios/raw.rs | 3 +- src/libstd/os/linux/raw.rs | 3 +- src/libstd/os/macos/raw.rs | 3 +- src/libstd/os/nacl/raw.rs | 3 +- src/libstd/os/netbsd/raw.rs | 3 +- src/libstd/os/openbsd/raw.rs | 3 +- src/libstd/os/solaris/raw.rs | 3 +- src/libstd/panic.rs | 162 +- src/libstd/path.rs | 48 +- src/libstd/primitive_docs.rs | 8 +- src/libstd/process.rs | 25 +- src/libstd/rt.rs | 5 +- src/libstd/sync/mpsc/blocking.rs | 14 +- src/libstd/sync/mpsc/mod.rs | 302 ++- src/libstd/sync/mpsc/oneshot.rs | 15 +- src/libstd/sync/mpsc/shared.rs | 17 +- src/libstd/sync/mpsc/spsc_queue.rs | 13 +- src/libstd/sync/mpsc/stream.rs | 15 +- src/libstd/sync/mpsc/sync.rs | 75 +- src/libstd/sync/mutex.rs | 6 +- src/libstd/sync/rwlock.rs | 105 +- src/libstd/sys/common/mutex.rs | 6 + src/libstd/sys/common/net.rs | 24 +- src/libstd/sys/common/util.rs | 26 +- src/libstd/sys/common/wtf8.rs | 10 +- src/libstd/sys/unix/ext/process.rs | 20 - src/libstd/sys/unix/ext/raw.rs | 2 +- src/libstd/sys/unix/fd.rs | 31 +- src/libstd/sys/unix/fs.rs | 2 +- src/libstd/sys/unix/mod.rs | 25 +- src/libstd/sys/unix/mutex.rs | 33 + src/libstd/sys/unix/net.rs | 8 +- src/libstd/sys/unix/pipe.rs | 19 +- src/libstd/sys/unix/process.rs | 11 - src/libstd/sys/unix/rwlock.rs | 76 +- src/libstd/sys/unix/thread.rs | 21 +- src/libstd/sys/windows/c.rs | 1 + src/libstd/sys/windows/fs.rs | 6 +- src/libstd/sys/windows/mod.rs | 20 +- src/libstd/sys/windows/mutex.rs | 2 + src/libstd/sys/windows/net.rs | 24 +- src/libstd/thread/local.rs | 42 +- src/libstd/thread/mod.rs | 142 +- src/libstd/thread/scoped_tls.rs | 298 --- src/libstd/time/mod.rs | 15 - src/libsyntax/Cargo.toml | 2 + src/libsyntax/ast.rs | 633 ++---- src/libsyntax/attr.rs | 326 ++- src/libsyntax/codemap.rs | 1585 +++++++------ src/libsyntax/config.rs | 612 ++--- src/libsyntax/diagnostic_list.rs | 54 + src/libsyntax/diagnostics/metadata.rs | 2 +- src/libsyntax/diagnostics/plugin.rs | 7 +- src/libsyntax/errors/snippet/test.rs | 583 ----- src/libsyntax/ext/base.rs | 195 +- src/libsyntax/ext/build.rs | 94 +- src/libsyntax/ext/expand.rs | 1500 ++++--------- src/libsyntax/ext/mtwt.rs | 379 +--- src/libsyntax/ext/quote.rs | 70 +- src/libsyntax/ext/source_util.rs | 29 +- src/libsyntax/ext/tt/macro_parser.rs | 32 +- src/libsyntax/ext/tt/macro_rules.rs | 347 +-- src/libsyntax/ext/tt/transcribe.rs | 27 +- src/libsyntax/feature_gate.rs | 204 +- src/libsyntax/fold.rs | 220 +- src/libsyntax/{errors => }/json.rs | 16 +- src/libsyntax/lib.rs | 32 +- src/libsyntax/parse/attr.rs | 12 +- src/libsyntax/parse/classify.rs | 10 +- src/libsyntax/parse/lexer/comments.rs | 5 +- src/libsyntax/parse/lexer/mod.rs | 65 +- src/libsyntax/parse/lexer/unicode_chars.rs | 2 +- src/libsyntax/parse/mod.rs | 69 +- src/libsyntax/parse/obsolete.rs | 2 +- src/libsyntax/parse/parser.rs | 837 ++++--- src/libsyntax/parse/token.rs | 3 +- src/libsyntax/print/pp.rs | 4 +- src/libsyntax/print/pprust.rs | 1976 ++++++++--------- src/libsyntax/show_span.rs | 2 +- src/libsyntax/std_inject.rs | 176 +- src/libsyntax/test.rs | 46 +- src/libsyntax/tokenstream.rs | 210 ++ src/libsyntax/util/interner.rs | 10 +- src/libsyntax/util/node_count.rs | 76 +- src/libsyntax/util/parser_testing.rs | 5 +- src/libsyntax/util/small_vector.rs | 19 + src/libsyntax/util/thin_vec.rs | 59 + src/libsyntax/visit.rs | 311 ++- src/libsyntax_ext/Cargo.toml | 2 + src/libsyntax_ext/asm.rs | 11 +- src/libsyntax_ext/cfg.rs | 15 +- src/libsyntax_ext/concat.rs | 7 +- src/libsyntax_ext/concat_idents.rs | 57 +- src/libsyntax_ext/deriving/bounds.rs | 2 +- src/libsyntax_ext/deriving/clone.rs | 12 +- src/libsyntax_ext/deriving/cmp/eq.rs | 4 +- src/libsyntax_ext/deriving/cmp/ord.rs | 2 +- src/libsyntax_ext/deriving/cmp/partial_eq.rs | 2 +- src/libsyntax_ext/deriving/cmp/partial_ord.rs | 2 +- src/libsyntax_ext/deriving/debug.rs | 16 +- src/libsyntax_ext/deriving/decodable.rs | 2 +- src/libsyntax_ext/deriving/default.rs | 2 +- src/libsyntax_ext/deriving/encodable.rs | 4 +- src/libsyntax_ext/deriving/generic/mod.rs | 100 +- src/libsyntax_ext/deriving/generic/ty.rs | 13 +- src/libsyntax_ext/deriving/hash.rs | 4 +- src/libsyntax_ext/deriving/mod.rs | 64 +- src/libsyntax_ext/env.rs | 16 +- src/libsyntax_ext/format.rs | 45 +- src/libsyntax_ext/lib.rs | 2 + src/libsyntax_ext/log_syntax.rs | 8 +- src/libsyntax_ext/trace_macros.rs | 5 +- src/libsyntax_pos/Cargo.toml | 12 + src/libsyntax_pos/lib.rs | 667 ++++++ src/libtest/lib.rs | 9 +- src/libtest/stats.rs | 3 +- src/libunwind/lib.rs | 1 - src/libunwind/libunwind.rs | 47 +- src/rt/hoedown/src/document.c | 6 +- src/rt/hoedown/src/html_blocks.c | 240 -- src/rt/miniz.c | 10 +- src/rtstartup/rsbegin.rs | 8 +- src/rtstartup/rsend.rs | 3 +- .../test/rust-installer-v1/README.md | 30 + .../rust-installer-v1/gen-install-script.sh | 253 +++ .../test/rust-installer-v1/gen-installer.sh | 303 +++ .../rust-installer-v1/install-template.sh | 554 +++++ .../test/rust-installer-v2/.gitmodules | 3 + .../test/rust-installer-v2/.travis.yml | 2 + .../test/rust-installer-v2/README.md | 74 + .../rust-installer-v2/combine-installers.sh | 347 +++ .../rust-installer-v2/gen-install-script.sh | 261 +++ .../test/rust-installer-v2/gen-installer.sh | 332 +++ .../rust-installer-v2/install-template.sh | 743 +++++++ .../rust-installer-v2/rust-installer-version | 1 + .../test/rust-installer-v2/test.sh | 588 +++++ .../rust-installer-v2/test/image1/bin/bad-bin | 1 + .../rust-installer-v2/test/image1/bin/program | 1 + .../test/image1/bin/program2 | 1 + .../test/image1/dir-to-install/foo | 0 .../test/image1/dir-to-not-install/foo | 0 .../test/image1/something-to-install | 0 .../test/image1/something-to-not-install | 0 .../test/image2/bin/oldprogram | 1 + .../test/image2/dir-to-install/bar | 0 .../test/image2/something-to-install | 0 .../rust-installer-v2/test/image3/bin/cargo | 1 + .../test/rust-installer-v2/test/image4/baz | 0 .../test/image4/dir-to-install/qux/bar | 0 .../test/image5/dir-to-install/foo | 0 .../test/rust-installer-v1/README.md | 30 + .../rust-installer-v1/gen-install-script.sh | 253 +++ .../test/rust-installer-v1/gen-installer.sh | 303 +++ .../rust-installer-v1/install-template.sh | 554 +++++ src/rustc/Cargo.lock | 51 +- src/rustllvm/ArchiveWrapper.cpp | 28 +- src/rustllvm/ExecutionEngineWrapper.cpp | 5 - src/rustllvm/PassWrapper.cpp | 53 +- src/rustllvm/RustWrapper.cpp | 143 +- src/stage0.txt | 6 +- .../cross-crate-trait-method.rs | 2 - .../item-collection/generic-functions.rs | 2 - .../item-collection/generic-impl.rs | 2 - .../instantiation-through-vtable.rs | 2 + .../codegen-units/item-collection/unsizing.rs | 2 + .../partitioning/local-generic.rs | 2 - src/test/codegen/issue-32031.rs | 33 + src/test/codegen/issue-32364.rs | 24 + src/test/codegen/loads.rs | 3 + src/test/codegen/naked-functions.rs | 4 +- src/test/codegen/zip.rs | 22 + .../auxiliary/macro_crate_test.rs | 6 +- src/test/compile-fail-fulldeps/gated-quote.rs | 2 +- src/test/compile-fail-fulldeps/issue-18986.rs | 3 +- src/test/compile-fail-fulldeps/qquote.rs | 6 +- src/test/compile-fail/E0055.rs | 1 - .../build.rs => test/compile-fail/E0062.rs} | 11 +- src/test/compile-fail/E0063.rs | 18 + src/test/compile-fail/E0067.rs | 16 + src/test/compile-fail/E0069.rs | 16 + src/test/compile-fail/E0070.rs | 23 + src/test/compile-fail/E0071.rs | 16 + src/test/compile-fail/E0072.rs | 17 + src/test/compile-fail/E0075.rs | 17 + src/test/compile-fail/E0076.rs | 17 + src/test/compile-fail/E0077.rs | 17 + src/test/compile-fail/E0079.rs | 16 + src/test/compile-fail/E0080.rs | 17 + src/test/compile-fail/E0081.rs | 18 + src/test/compile-fail/E0084.rs | 15 + src/test/compile-fail/E0087.rs | 15 + src/test/compile-fail/E0088.rs | 15 + src/test/compile-fail/E0089.rs | 15 + src/test/compile-fail/E0091.rs | 15 + src/test/compile-fail/E0092.rs | 17 + src/test/compile-fail/E0093.rs | 17 + src/test/compile-fail/E0094.rs | 17 + src/test/compile-fail/E0101.rs | 13 + src/test/compile-fail/E0102.rs | 13 + src/test/compile-fail/E0106.rs | 21 + src/test/compile-fail/E0107.rs | 25 + src/test/compile-fail/E0109.rs | 14 + src/test/compile-fail/E0110.rs | 14 + src/test/compile-fail/E0116.rs | 14 + src/test/compile-fail/E0117.rs | 14 + src/test/compile-fail/{E0024.rs => E0118.rs} | 12 +- src/test/compile-fail/E0119.rs | 28 + src/test/compile-fail/E0120.rs | 18 + src/test/compile-fail/E0121.rs | 16 + src/test/compile-fail/E0124.rs | 17 + src/test/compile-fail/E0128.rs | 17 + src/test/compile-fail/E0130.rs | 16 + src/test/compile-fail/E0131.rs | 12 + src/test/compile-fail/E0132.rs | 17 + src/test/compile-fail/E0133.rs | 15 + src/test/compile-fail/E0137.rs | 17 + src/test/compile-fail/E0138.rs | 17 + src/test/compile-fail/E0152.rs | 17 + src/test/compile-fail/E0161.rs | 16 + src/test/compile-fail/E0162.rs | 18 + src/test/compile-fail/E0163.rs | 20 + src/test/compile-fail/E0164.rs | 20 + src/test/compile-fail/E0165.rs | 18 + src/test/compile-fail/E0166.rs | 14 + src/test/compile-fail/E0172.rs | 14 + src/test/compile-fail/E0178.rs | 21 + src/test/compile-fail/E0184.rs | 20 + src/test/compile-fail/E0185.rs | 22 + src/test/compile-fail/E0186.rs | 22 + src/test/compile-fail/E0191.rs | 18 + src/test/compile-fail/E0192.rs | 22 + src/test/compile-fail/E0194.rs | 17 + src/test/compile-fail/E0195.rs | 23 + src/test/compile-fail/E0197.rs | 16 + src/test/compile-fail/E0199.rs | 18 + src/test/compile-fail/E0200.rs | 18 + src/test/compile-fail/array_const_index-0.rs | 2 +- src/test/compile-fail/array_const_index-1.rs | 3 +- src/test/compile-fail/asm-misplaced-option.rs | 2 + .../associated-const-private-impl.rs | 2 +- .../associated-types/cache/chrono-scan.rs | 39 + .../associated-types/cache/elision.rs | 34 + .../cache/project-fn-ret-contravariant.rs | 65 + .../cache/project-fn-ret-invariant.rs | 76 + .../cache/wasm-issue-32330.rs | 49 + .../auxiliary/recursive_reexports.rs | 13 + src/test/compile-fail/bad-format-args.rs | 22 + .../compile-fail/blind-item-block-middle.rs | 2 +- ...rrowck-borrow-overloaded-auto-deref-mut.rs | 2 +- .../borrowck/borrowck-move-out-of-vec-tail.rs | 8 +- .../borrowck-vec-pattern-element-loan.rs | 6 +- .../borrowck-vec-pattern-loan-from-mut.rs | 2 +- .../borrowck-vec-pattern-move-tail.rs | 2 +- .../borrowck/borrowck-vec-pattern-nesting.rs | 15 +- .../borrowck-vec-pattern-tail-element-loan.rs | 2 +- src/test/compile-fail/cfg-non-opt-expr.rs | 2 + src/test/compile-fail/const-array-oob.rs | 4 +- src/test/compile-fail/const-err-early.rs | 6 +- src/test/compile-fail/const-err.rs | 10 +- src/test/compile-fail/const-eval-overflow.rs | 2 - .../compile-fail/const-pattern-irrefutable.rs | 12 +- src/test/compile-fail/const-slice-oob.rs | 3 +- src/test/compile-fail/const-unsized.rs | 35 + src/test/compile-fail/custom_attribute.rs | 7 +- .../compile-fail/empty-struct-braces-pat-2.rs | 4 +- src/test/compile-fail/enum-in-scope.rs | 2 +- .../compile-fail/enums-pats-not-idents.rs | 5 +- src/test/compile-fail/expanded-cfg.rs | 8 +- src/test/compile-fail/hr-subtype.rs | 119 + src/test/compile-fail/ifmt-bad-arg.rs | 4 - .../compile-fail/invalid-macro-matcher.rs | 2 +- src/test/compile-fail/issue-10200.rs | 2 +- src/test/compile-fail/issue-12369.rs | 8 +- src/test/compile-fail/issue-12560-1.rs | 2 +- src/test/compile-fail/issue-12567.rs | 12 +- src/test/compile-fail/issue-12863.rs | 2 +- src/test/compile-fail/issue-13482-2.rs | 6 +- src/test/compile-fail/issue-13482.rs | 6 +- src/test/compile-fail/issue-13727.rs | 22 + src/test/compile-fail/issue-15381.rs | 4 +- src/test/compile-fail/issue-16048.rs | 2 +- src/test/compile-fail/issue-16149.rs | 2 +- src/test/compile-fail/issue-16338.rs | 9 +- src/test/compile-fail/issue-16401.rs | 9 +- src/test/compile-fail/issue-17405.rs | 3 +- .../compile-fail/issue-17718-const-privacy.rs | 4 +- src/test/compile-fail/issue-17718-patterns.rs | 4 +- src/test/compile-fail/issue-17933.rs | 2 +- src/test/compile-fail/issue-18819.rs | 1 + src/test/compile-fail/issue-20831-debruijn.rs | 1 - .../input.rs => compile-fail/issue-22434.rs} | 8 +- src/test/compile-fail/issue-23122-1.rs | 22 + src/test/compile-fail/issue-23122-2.rs | 22 + src/test/compile-fail/issue-23281.rs | 20 + src/test/compile-fail/issue-2356.rs | 7 +- src/test/compile-fail/issue-23716.rs | 12 +- src/test/compile-fail/issue-24424.rs | 18 + src/test/compile-fail/issue-24446.rs | 2 + src/test/compile-fail/issue-24819.rs | 21 + src/test/compile-fail/issue-25579.rs | 27 + src/test/compile-fail/issue-26459.rs | 3 +- src/test/compile-fail/issue-26548.rs | 3 + src/test/compile-fail/issue-27033.rs | 4 +- src/test/compile-fail/issue-27815.rs | 6 +- src/test/compile-fail/issue-28992-empty.rs | 2 +- src/test/compile-fail/issue-29161.rs | 2 +- src/test/compile-fail/issue-30240.rs | 21 + src/test/compile-fail/issue-3044.rs | 1 + src/test/compile-fail/issue-30715.rs | 33 - src/test/compile-fail/issue-32004.rs | 4 +- src/test/compile-fail/issue-32086.rs | 17 + src/test/compile-fail/issue-32829.rs | 17 + src/test/compile-fail/issue-32950.rs | 18 + src/test/compile-fail/issue-33293.rs | 16 + src/test/compile-fail/issue-33571.rs | 14 + src/test/compile-fail/issue-33819.rs | 18 + src/test/compile-fail/issue-33876.rs | 26 + src/test/compile-fail/issue-34028.rs | 21 + src/test/compile-fail/issue-34047.rs | 19 + src/test/compile-fail/issue-34171.rs | 21 + src/test/compile-fail/issue-34194.rs | 21 + src/test/compile-fail/issue-34209.rs | 23 + src/test/compile-fail/issue-34334.rs | 15 + src/test/compile-fail/issue-34349.rs | 32 + src/test/compile-fail/issue-34418.rs | 31 + src/test/compile-fail/issue-35044.rs | 46 + src/test/compile-fail/issue-4935.rs | 1 + src/test/compile-fail/issue-5927.rs | 2 +- src/test/compile-fail/label-static.rs | 15 + ...me-inference-give-expl-lifetime-param-3.rs | 2 +- ...time-inference-give-expl-lifetime-param.rs | 2 +- src/test/compile-fail/lifetime-underscore.rs | 27 + .../compile-fail/macro-backtrace-println.rs | 8 +- src/test/compile-fail/macro-error.rs | 7 +- .../macro-expanded-include/file.txt | 0 .../macro-expanded-include/foo/mod.rs | 19 + .../macro-expanded-include/test.rs | 21 + src/test/compile-fail/macro-follow.rs | 22 +- .../macro-invalid-fragment-spec.rs | 19 + .../compile-fail/macro-missing-delimiters.rs | 17 + src/test/compile-fail/macro-use-scope.rs | 32 + .../compile-fail/macro-with-seps-err-msg.rs | 6 +- .../compile-fail/macros-nonfatal-errors.rs | 1 - src/test/compile-fail/malformed_macro_lhs.rs | 4 +- .../match-pattern-field-mismatch-2.rs | 2 +- src/test/compile-fail/match-vec-mismatch-2.rs | 5 +- src/test/compile-fail/match-vec-mismatch.rs | 33 +- .../compile-fail/match-vec-unreachable.rs | 8 +- src/test/compile-fail/method-call-err-msg.rs | 3 + .../method-resolvable-path-in-pattern.rs | 2 +- src/test/compile-fail/mir-dataflow/README.md | 53 + .../compile-fail/mir-dataflow/def-inits-1.rs | 63 + src/test/compile-fail/mir-dataflow/inits-1.rs | 65 + .../compile-fail/mir-dataflow/uninits-1.rs | 63 + .../compile-fail/mir-dataflow/uninits-2.rs | 36 + src/test/compile-fail/name-clash-nullary.rs | 5 +- src/test/compile-fail/nested-cfg-attrs.rs | 14 + .../no-warn-on-field-replace-issue-34101.rs | 56 + .../non-exhaustive-match-nested.rs | 10 +- src/test/compile-fail/non-exhaustive-match.rs | 22 +- .../non-exhaustive-pattern-witness.rs | 4 +- src/test/compile-fail/non-interger-atomic.rs | 8 +- src/test/compile-fail/not-enough-arguments.rs | 1 + src/test/compile-fail/not-panic-safe-2.rs | 5 +- src/test/compile-fail/not-panic-safe-3.rs | 5 +- src/test/compile-fail/not-panic-safe-4.rs | 5 +- src/test/compile-fail/not-panic-safe-5.rs | 5 +- src/test/compile-fail/not-panic-safe-6.rs | 5 +- src/test/compile-fail/overloaded-calls-bad.rs | 8 +- .../pat-shadow-in-nested-binding.rs | 2 +- src/test/compile-fail/pat-slice-old-style.rs | 22 + src/test/compile-fail/pat-tuple-bad-type.rs | 27 + .../compile-fail/pat-tuple-feature-gate.rs | 17 + src/test/compile-fail/pat-tuple-overfield.rs | 28 + .../compile-fail/pattern-error-continue.rs | 2 +- .../compile-fail/priv-in-bad-locations.rs | 9 +- .../privacy/restricted/ty-params.rs | 2 + .../compile-fail/qualified-path-params.rs | 2 +- src/test/compile-fail/range-1.rs | 5 +- src/test/compile-fail/range_traits-1.rs | 93 + src/test/compile-fail/range_traits-2.rs | 17 + src/test/compile-fail/range_traits-3.rs | 17 + src/test/compile-fail/range_traits-4.rs | 20 + src/test/compile-fail/range_traits-5.rs | 20 + src/test/compile-fail/range_traits-6.rs | 19 + src/test/compile-fail/range_traits-7.rs | 20 + src/test/compile-fail/recursive-reexports.rs | 15 + .../regions-bound-missing-bound-in-impl.rs | 3 +- .../regions-close-over-type-parameter-1.rs | 4 +- .../regions-early-bound-error-method.rs | 6 +- .../compile-fail/regions-early-bound-error.rs | 2 +- ...ns-infer-invariance-due-to-mutability-4.rs | 2 +- src/test/compile-fail/regions-trait-1.rs | 2 +- .../stability-attribute-sanity.rs | 49 +- src/test/compile-fail/stable-features.rs | 4 +- src/test/compile-fail/static-mut-not-pat.rs | 4 +- .../suggest-path-instead-of-mod-dot-item.rs | 18 +- src/test/compile-fail/symbol-names/impl1.rs | 2 +- .../compile-fail/syntax-extension-minor.rs | 9 +- src/test/compile-fail/trace_macros-gate.rs | 4 +- .../compile-fail/trait-impl-for-module.rs | 2 +- .../unresolved_static_type_field.rs | 24 + .../compile-fail/use-super-global-path.rs | 9 +- src/test/compile-fail/useless-pub.rs | 4 +- src/test/compile-fail/variadic-ffi-3.rs | 2 + .../debuginfo/function-arg-initialization.rs | 8 +- ...nction-prologue-stepping-no-stack-check.rs | 13 +- src/test/debuginfo/pretty-huge-vec.rs | 41 + .../debuginfo/pretty-uninitialized-vec.rs | 36 + src/test/debuginfo/vec-slices.rs | 7 + src/test/incremental/struct_add_field.rs | 48 + .../incremental/struct_change_field_name.rs | 55 + .../incremental/struct_change_field_type.rs | 53 + .../auxiliary/a.rs | 29 + .../struct_change_field_type_cross_crate/b.rs | 36 + src/test/incremental/struct_change_nothing.rs | 53 + src/test/incremental/struct_remove_field.rs | 52 + .../type_alias_cross_crate/auxiliary/a.rs | 6 +- .../incremental/type_alias_cross_crate/b.rs | 4 +- src/test/parse-fail/issue-33455.rs | 11 + src/test/parse-fail/issue-33569.rs | 18 + src/test/parse-fail/pat-lt-bracket-6.rs | 3 +- src/test/parse-fail/pat-lt-bracket-7.rs | 3 +- src/test/parse-fail/pat-tuple-1.rs | 17 + src/test/parse-fail/pat-tuple-2.rs | 17 + src/test/parse-fail/pat-tuple-3.rs | 17 + src/test/parse-fail/pat-tuple-4.rs | 17 + src/test/parse-fail/pat-tuple-5.rs | 17 + src/test/parse-fail/pat-tuple-6.rs | 17 + .../trait-non-item-macros.rs} | 13 +- src/test/pretty/attr-variant-data.rs | 51 + src/test/pretty/lifetime.rs | 15 + src/test/pretty/where-clauses.rs | 2 +- src/test/run-fail-fulldeps/qquote.rs | 8 +- src/test/run-fail/args-panic.rs | 8 +- src/test/run-fail/assert-eq-macro-panic.rs | 2 +- src/test/run-fail/binop-fail-3.rs | 4 +- src/test/run-fail/binop-panic.rs | 9 +- .../bug-2470-bounds-check-overflow.rs | 4 +- src/test/run-fail/bug-811.rs | 12 +- src/test/run-fail/divide-by-zero.rs | 2 - src/test/run-fail/doublepanic.rs | 2 +- src/test/run-fail/explicit-panic-msg.rs | 4 +- src/test/run-fail/explicit-panic.rs | 4 +- src/test/run-fail/expr-fn-panic.rs | 8 +- src/test/run-fail/expr-if-panic-fn.rs | 17 +- src/test/run-fail/expr-if-panic.rs | 10 +- src/test/run-fail/expr-match-panic-fn.rs | 16 +- src/test/run-fail/expr-match-panic.rs | 7 +- src/test/run-fail/for-each-loop-panic.rs | 6 +- src/test/run-fail/if-check-panic.rs | 10 +- src/test/run-fail/if-cond-bot.rs | 10 +- src/test/run-fail/issue-12920.rs | 3 +- src/test/run-fail/issue-18576.rs | 2 +- src/test/run-fail/issue-20971.rs | 9 +- src/test/run-fail/issue-2444.rs | 10 +- src/test/run-fail/issue-28934.rs | 9 +- src/test/run-fail/issue-3029.rs | 2 +- src/test/run-fail/issue-30380.rs | 47 + src/test/run-fail/issue-6458-1.rs | 4 +- src/test/run-fail/issue-948.rs | 9 +- src/test/run-fail/main-panic.rs | 2 +- src/test/run-fail/match-bot-panic.rs | 8 +- src/test/run-fail/match-disc-bot.rs | 15 +- src/test/run-fail/match-wildcards.rs | 16 +- src/test/run-fail/meta-revision-bad.rs | 14 +- src/test/run-fail/meta-revision-ok.rs | 14 +- src/test/run-fail/mir_dynamic_drops_1.rs | 2 +- src/test/run-fail/mir_dynamic_drops_2.rs | 2 +- src/test/run-fail/mir_dynamic_drops_3.rs | 2 +- src/test/run-fail/mod-zero.rs | 4 +- src/test/run-fail/overflowing-add.rs | 4 +- src/test/run-fail/overflowing-lsh-1.rs | 4 +- src/test/run-fail/overflowing-lsh-2.rs | 4 +- src/test/run-fail/overflowing-lsh-3.rs | 4 +- src/test/run-fail/overflowing-lsh-4.rs | 4 +- src/test/run-fail/overflowing-mul.rs | 4 +- src/test/run-fail/overflowing-neg.rs | 4 +- src/test/run-fail/overflowing-pow.rs | 2 +- src/test/run-fail/overflowing-rsh-1.rs | 4 +- src/test/run-fail/overflowing-rsh-2.rs | 4 +- src/test/run-fail/overflowing-rsh-3.rs | 4 +- src/test/run-fail/overflowing-rsh-4.rs | 4 +- src/test/run-fail/overflowing-rsh-5.rs | 4 +- src/test/run-fail/overflowing-rsh-6.rs | 4 +- src/test/run-fail/overflowing-sub.rs | 4 +- src/test/run-fail/panic-arg.rs | 8 +- src/test/run-fail/panic-macro-any.rs | 2 +- src/test/run-fail/panic-main.rs | 4 +- src/test/run-fail/panic-parens.rs | 14 +- src/test/run-fail/panic-set-handler.rs | 7 +- src/test/run-fail/panic-set-unset-handler.rs | 11 +- src/test/run-fail/panic-take-handler-nop.rs | 7 +- src/test/run-fail/panic-task-name-none.rs | 7 +- src/test/run-fail/panic-task-name-owned.rs | 13 +- src/test/run-fail/panic.rs | 4 +- src/test/run-fail/result-get-panic.rs | 2 +- src/test/run-fail/rhs-type.rs | 6 +- src/test/run-fail/run-unexported-tests.rs | 6 +- .../run-fail/unimplemented-macro-panic.rs | 4 +- src/test/run-fail/unique-panic.rs | 4 +- src/test/run-fail/unreachable-macro-panic.rs | 4 +- src/test/run-fail/unreachable-static-msg.rs | 4 +- src/test/run-fail/unreachable.rs | 4 +- src/test/run-fail/unwind-interleaved.rs | 10 +- src/test/run-fail/unwind-rec.rs | 8 +- src/test/run-fail/unwind-rec2.rs | 9 +- src/test/run-fail/vec-overrun.rs | 2 +- src/test/run-fail/while-body-panics.rs | 9 +- src/test/run-fail/while-panic.rs | 7 +- .../atomic-lock-free/atomic_lock_free.rs | 2 + src/test/run-make/debug-assertions/debug.rs | 1 - .../run-make/dep-info-no-analysis/Makefile | 6 - .../run-make/dep-info-no-analysis/input.dd | 3 - src/test/run-make/execution-engine/test.rs | 17 +- src/test/run-make/issue-19371/foo.rs | 3 +- src/test/run-make/llvm-phase/Makefile | 5 + src/test/run-make/llvm-phase/test.rs | 82 + .../run-make/unicode-input/span_length.rs | 65 +- .../run-pass-fulldeps/ast_stmt_expr_attr.rs | 2 +- .../auxiliary/custom_derive_plugin.rs | 3 +- .../auxiliary/custom_derive_plugin_attr.rs | 3 +- .../auxiliary/dummy_mir_pass.rs | 1 + .../issue_16723_multiple_items_syntax_ext.rs | 6 +- .../auxiliary/macro_crate_test.rs | 23 +- .../auxiliary/plugin_args.rs | 6 +- .../auxiliary/procedural_mbe_matching.rs | 6 +- .../auxiliary/roman_numerals.rs | 5 +- .../syntax_extension_with_dll_deps_2.rs | 6 +- src/test/run-pass-fulldeps/compiler-calls.rs | 6 +- src/test/run-pass-fulldeps/macro-crate.rs | 2 + src/test/run-pass-fulldeps/qquote.rs | 7 +- src/test/run-pass-fulldeps/quote-tokens.rs | 6 +- src/test/run-pass/assert-eq-macro-success.rs | 3 + src/test/run-pass/auxiliary/issue34796aux.rs | 30 + .../xcrate_generic_fn_nested_return.rs | 26 + src/test/run-pass/binary-heap-panic-safe.rs | 8 +- src/test/run-pass/coherence-subtyping.rs | 12 +- src/test/run-pass/const-byte-str-cast.rs | 15 + src/test/run-pass/dropck_legal_cycles.rs | 22 +- src/test/run-pass/dynamic-drop.rs | 156 ++ .../run-pass/exhaustive-bool-match-sanity.rs | 34 + src/test/run-pass/hygiene.rs | 116 + src/test/run-pass/issue-15080.rs | 6 +- src/test/run-pass/issue-15104.rs | 4 +- src/test/run-pass/issue-16648.rs | 7 +- src/test/run-pass/issue-21058.rs | 2 +- src/test/run-pass/issue-23477.rs | 23 + .../{issue-23598.rs => issue-23958.rs} | 0 src/test/run-pass/issue-30240.rs | 23 + src/test/run-pass/issue-30276.rs | 14 + src/test/run-pass/issue-32805.rs | 26 + src/test/run-pass/issue-33770.rs | 100 + src/test/run-pass/issue-34074.rs | 18 + src/test/run-pass/issue-34932.rs | 23 + src/test/run-pass/issue-7784.rs | 2 + src/test/run-pass/issue-8460.rs | 2 - src/test/run-pass/issue34796.rs | 36 + src/test/run-pass/match-unsized.rs | 18 + src/test/run-pass/match-vec-alternatives.rs | 40 +- .../run-pass/mir_call_with_associated_type.rs | 29 + src/test/run-pass/mir_cast_fn_ret.rs | 34 + src/test/run-pass/mir_constval_adts.rs | 14 +- src/test/run-pass/mir_trans_calls.rs | 27 + src/test/run-pass/multi-panic.rs | 2 +- src/test/run-pass/panic-recover-propagate.rs | 14 +- src/test/run-pass/pat-tuple-1.rs | 104 + src/test/run-pass/pat-tuple-2.rs | 34 + src/test/run-pass/pat-tuple-3.rs | 40 + src/test/run-pass/pat-tuple-4.rs | 68 + src/test/run-pass/pat-tuple-5.rs | 40 + src/test/run-pass/pat-tuple-6.rs | 56 + .../run-pass/project-cache-issue-31849.rs | 75 + src/test/run-pass/range_inclusive.rs | 5 - .../run-pass/reachable-unnameable-items.rs | 4 +- src/test/run-pass/running-with-no-runtime.rs | 6 +- src/test/run-pass/sleep.rs | 25 + src/test/run-pass/test-vs-cfg-test.rs | 18 + src/test/run-pass/thread-local-syntax.rs | 23 + src/test/run-pass/trait-item-inside-macro.rs | 39 + src/test/run-pass/utf8_chars.rs | 2 - src/test/run-pass/variadic-ffi.rs | 67 +- src/test/run-pass/vec-matching-fold.rs | 24 +- .../vec-matching-legal-tail-element-borrow.rs | 5 +- src/test/run-pass/vec-matching.rs | 77 +- src/test/run-pass/vec-tail-matching.rs | 22 +- .../xcrate_generic_fn_nested_return.rs | 17 + .../run-pass/zero_sized_subslice_match.rs | 5 +- src/test/rustdoc/auxiliary/issue-34274.rs | 13 + .../rustdoc/auxiliary/src-links-external.rs | 11 + src/test/rustdoc/deprecated-impls.rs | 128 ++ src/test/rustdoc/hidden-impls.rs | 27 + src/test/rustdoc/hidden-methods.rs | 39 + src/test/rustdoc/inline_cross/hidden-use.rs | 22 + src/test/rustdoc/inline_local/hidden-use.rs | 20 + src/test/rustdoc/issue-34025.rs | 22 + src/test/rustdoc/issue-34274.rs | 20 + src/test/rustdoc/issue-34423.rs | 20 + src/test/rustdoc/issue-34473.rs | 22 + src/test/rustdoc/module-impls.rs | 15 + src/test/rustdoc/redirect-const.rs | 23 + src/test/rustdoc/redirect-rename.rs | 32 + src/test/rustdoc/src-links-external.rs | 22 + .../mismatched_types}/issue-26480.rs | 12 +- .../ui/mismatched_types/issue-26480.stderr | 15 + src/test/ui/mismatched_types/main.stderr | 1 + src/tools/cargotest/main.rs | 76 +- src/tools/compiletest/src/json.rs | 2 +- src/tools/compiletest/src/main.rs | 15 + src/tools/compiletest/src/runtest.rs | 27 +- src/tools/linkchecker/main.rs | 106 +- src/tools/rustbook/main.rs | 1 - src/tools/tidy/src/cargo.rs | 9 +- 1604 files changed, 50373 insertions(+), 24931 deletions(-) create mode 100644 src/compiler-rt/lib/asan/.clang-format create mode 100644 src/compiler-rt/lib/builtins/divtc3.c create mode 100644 src/compiler-rt/lib/cfi/cfi.cc create mode 100644 src/compiler-rt/lib/dfsan/.clang-format create mode 100644 src/compiler-rt/lib/dfsan/dfsan_platform.h create mode 100644 src/compiler-rt/lib/interception/.clang-format create mode 100644 src/compiler-rt/lib/lsan/.clang-format create mode 100644 src/compiler-rt/lib/msan/.clang-format create mode 100644 src/compiler-rt/lib/profile/InstrProfData.inc create mode 100644 src/compiler-rt/lib/profile/InstrProfilingPort.h create mode 100644 src/compiler-rt/lib/profile/InstrProfilingValue.c create mode 100644 src/compiler-rt/lib/profile/InstrProfilingWriter.c create mode 100644 src/compiler-rt/lib/profile/WindowsMMap.c create mode 100644 src/compiler-rt/lib/profile/WindowsMMap.h create mode 100644 src/compiler-rt/lib/safestack/.clang-format create mode 100644 src/compiler-rt/lib/sanitizer_common/.clang-format create mode 100644 src/compiler-rt/lib/tsan/.clang-format delete mode 100644 src/compiler-rt/lib/tsan/Makefile.old delete mode 100755 src/compiler-rt/lib/tsan/check_memcpy.sh delete mode 100644 src/compiler-rt/lib/tsan/rtl/Makefile.old create mode 100644 src/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc create mode 100644 src/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc create mode 100644 src/compiler-rt/lib/tsan/rtl/tsan_ppc_regs.h create mode 100644 src/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S create mode 100644 src/compiler-rt/lib/tsan/rtl/tsan_rtl_ppc64.S rename src/compiler-rt/lib/tsan/tests/rtl/{tsan_test_util_linux.cc => tsan_test_util_posix.cc} (70%) create mode 100644 src/compiler-rt/make/platform/clang_darwin.mk create mode 100644 src/compiler-rt/make/platform/clang_darwin_test_input.c create mode 100644 src/compiler-rt/make/platform/clang_linux.mk create mode 100644 src/compiler-rt/make/platform/clang_linux_test_input.c create mode 100644 src/compiler-rt/make/platform/clang_macho_embedded.mk create mode 100644 src/compiler-rt/make/platform/clang_macho_embedded_test_input.c create mode 100644 src/compiler-rt/make/platform/clang_mingw.mk create mode 100644 src/compiler-rt/make/platform/darwin_bni.mk create mode 100644 src/compiler-rt/make/platform/multi_arch.mk delete mode 100644 src/compiler-rt/make/platform/triple.mk create mode 100644 src/compiler-rt/test/asan/TestCases/Linux/calloc-preload.c create mode 100644 src/compiler-rt/test/asan/TestCases/Linux/mincore.cc create mode 100644 src/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c create mode 100644 src/compiler-rt/test/asan/TestCases/Posix/halt_on_error-torture.cc create mode 100644 src/compiler-rt/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc create mode 100644 src/compiler-rt/test/asan/TestCases/coverage-pc-buffer.cc create mode 100644 src/compiler-rt/test/asan/TestCases/halt_on_error-1.c create mode 100644 src/compiler-rt/test/asan/TestCases/speculative_load2.cc create mode 100644 src/compiler-rt/test/cfi/cross-dso/icall/icall-from-dso.cpp create mode 100644 src/compiler-rt/test/cfi/cross-dso/icall/icall.cpp create mode 100644 src/compiler-rt/test/cfi/cross-dso/icall/lit.local.cfg create mode 100644 src/compiler-rt/test/cfi/cross-dso/lit.local.cfg create mode 100644 src/compiler-rt/test/cfi/cross-dso/simple-fail.cpp create mode 100644 src/compiler-rt/test/cfi/cross-dso/simple-pass.cpp rename src/compiler-rt/test/lsan/TestCases/{cleanup_in_tsd_destructor.cc => cleanup_in_tsd_destructor.c} (97%) create mode 100644 src/compiler-rt/test/lsan/TestCases/disabler.c rename src/compiler-rt/test/lsan/TestCases/{disabler_in_tsd_destructor.cc => disabler_in_tsd_destructor.c} (92%) rename src/compiler-rt/test/lsan/TestCases/{ignore_object.cc => ignore_object.c} (90%) create mode 100644 src/compiler-rt/test/msan/ctermid.cc create mode 100644 src/compiler-rt/test/msan/dlopen_executable.cc create mode 100644 src/compiler-rt/test/profile/Inputs/instrprof-shared-lib.c create mode 100644 src/compiler-rt/test/profile/Inputs/instrprof-shared-main.c create mode 100644 src/compiler-rt/test/profile/Linux/instrprof-basic.c create mode 100644 src/compiler-rt/test/profile/Linux/instrprof-dlopen.test create mode 100644 src/compiler-rt/test/profile/Linux/instrprof-dynamic-one-shared.test create mode 100644 src/compiler-rt/test/profile/Linux/instrprof-dynamic-two-shared.test create mode 100644 src/compiler-rt/test/profile/Linux/lit.local.cfg create mode 100644 src/compiler-rt/test/profile/instrprof-bufferio.c create mode 100644 src/compiler-rt/test/profile/instrprof-error.c create mode 100644 src/compiler-rt/test/profile/instrprof-shared.test create mode 100644 src/compiler-rt/test/profile/instrprof-value-prof-2.c create mode 100644 src/compiler-rt/test/profile/instrprof-value-prof.c create mode 100644 src/compiler-rt/test/profile/instrprof-version-mismatch.c create mode 100644 src/compiler-rt/test/sanitizer_common/TestCases/Linux/closedir.c create mode 100644 src/compiler-rt/test/sanitizer_common/TestCases/Linux/ill.cc create mode 100644 src/compiler-rt/test/sanitizer_common/TestCases/fopen_nullptr.c create mode 100644 src/compiler-rt/test/tsan/Darwin/gcd-async-norace.mm create mode 100644 src/compiler-rt/test/tsan/Darwin/gcd-async-race.mm create mode 100644 src/compiler-rt/test/tsan/Darwin/gcd-groups-norace.mm create mode 100644 src/compiler-rt/test/tsan/Darwin/gcd-groups-stress.mm create mode 100644 src/compiler-rt/test/tsan/Darwin/gcd-once.mm create mode 100644 src/compiler-rt/test/tsan/Darwin/gcd-semaphore-norace.mm create mode 100644 src/compiler-rt/test/tsan/Darwin/gcd-serial-queue-norace.mm create mode 100644 src/compiler-rt/test/tsan/Darwin/gcd-sync-norace.mm create mode 100644 src/compiler-rt/test/tsan/Darwin/gcd-sync-race.mm create mode 100644 src/compiler-rt/test/tsan/Darwin/lit.local.cfg create mode 100644 src/compiler-rt/test/tsan/Darwin/objc-race.mm create mode 100644 src/compiler-rt/test/tsan/Darwin/objc-simple.mm create mode 100644 src/compiler-rt/test/tsan/Darwin/osspinlock-norace.cc create mode 100644 src/compiler-rt/test/tsan/Darwin/symbolizer-atos.cc create mode 100644 src/compiler-rt/test/tsan/Darwin/symbolizer-dladdr.cc create mode 100644 src/compiler-rt/test/tsan/Linux/check_memcpy.cc create mode 100644 src/compiler-rt/test/tsan/fd_tid_recycled.cc create mode 100644 src/compiler-rt/test/tsan/pie_test.cc delete mode 100755 src/compiler-rt/test/tsan/test_output.sh create mode 100644 src/compiler-rt/test/ubsan/TestCases/Integer/suppressions.cpp create mode 100644 src/etc/Dockerfile create mode 100644 src/libcore/iter_private.rs create mode 100644 src/librustc/mir/cache.rs rename src/{librustc_mir => librustc/mir}/traversal.rs (92%) delete mode 100644 src/librustc_borrowck/borrowck/mir/dataflow.rs create mode 100644 src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs create mode 100644 src/librustc_borrowck/borrowck/mir/dataflow/impls.rs create mode 100644 src/librustc_borrowck/borrowck/mir/dataflow/mod.rs create mode 100644 src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs create mode 100644 src/librustc_borrowck/borrowck/mir/elaborate_drops.rs delete mode 100644 src/librustc_borrowck/borrowck/mir/graphviz.rs create mode 100644 src/librustc_borrowck/borrowck/mir/patch.rs create mode 100644 src/librustc_borrowck/indexed_set.rs create mode 100644 src/librustc_const_math/float.rs create mode 100644 src/librustc_data_structures/control_flow_graph/dominators/mod.rs create mode 100644 src/librustc_data_structures/control_flow_graph/dominators/test.rs create mode 100644 src/librustc_data_structures/control_flow_graph/iterate/mod.rs create mode 100644 src/librustc_data_structures/control_flow_graph/iterate/test.rs create mode 100644 src/librustc_data_structures/control_flow_graph/mod.rs create mode 100644 src/librustc_data_structures/control_flow_graph/reachable/mod.rs create mode 100644 src/librustc_data_structures/control_flow_graph/reachable/test.rs create mode 100644 src/librustc_data_structures/control_flow_graph/reference.rs create mode 100644 src/librustc_data_structures/control_flow_graph/test.rs create mode 100644 src/librustc_data_structures/control_flow_graph/transpose.rs create mode 100644 src/librustc_data_structures/indexed_vec.rs create mode 100644 src/librustc_data_structures/snapshot_map/mod.rs create mode 100644 src/librustc_data_structures/snapshot_map/test.rs create mode 100644 src/librustc_errors/Cargo.toml rename src/{libsyntax/errors => librustc_errors}/emitter.rs (68%) rename src/{libsyntax/errors/mod.rs => librustc_errors/lib.rs} (92%) rename src/{libsyntax/diagnostics => librustc_errors}/registry.rs (100%) rename src/{libsyntax/errors/snippet/mod.rs => librustc_errors/snippet.rs} (93%) create mode 100644 src/librustc_mir/transform/add_call_guards.rs delete mode 100644 src/librustc_mir/transform/break_cleanup_edges.rs create mode 100644 src/librustc_mir/transform/dump_mir.rs delete mode 100644 src/librustc_mir/transform/remove_dead_blocks.rs create mode 100644 src/librustc_mir/transform/simplify_branches.rs create mode 100644 src/librustc_passes/ast_validation.rs create mode 100644 src/librustc_trans/back/msvc/arch.rs delete mode 100644 src/librustc_trans/mir/drop.rs create mode 100644 src/librustc_typeck/check/autoderef.rs delete mode 100644 src/libstd/thread/scoped_tls.rs create mode 100644 src/libsyntax/diagnostic_list.rs delete mode 100644 src/libsyntax/errors/snippet/test.rs rename src/libsyntax/{errors => }/json.rs (97%) create mode 100644 src/libsyntax/tokenstream.rs create mode 100644 src/libsyntax/util/thin_vec.rs create mode 100644 src/libsyntax_pos/Cargo.toml create mode 100644 src/libsyntax_pos/lib.rs delete mode 100644 src/rt/hoedown/src/html_blocks.c create mode 100644 src/rust-installer/test/rust-installer-v1/README.md create mode 100755 src/rust-installer/test/rust-installer-v1/gen-install-script.sh create mode 100755 src/rust-installer/test/rust-installer-v1/gen-installer.sh create mode 100644 src/rust-installer/test/rust-installer-v1/install-template.sh create mode 100644 src/rust-installer/test/rust-installer-v2/.gitmodules create mode 100644 src/rust-installer/test/rust-installer-v2/.travis.yml create mode 100644 src/rust-installer/test/rust-installer-v2/README.md create mode 100644 src/rust-installer/test/rust-installer-v2/combine-installers.sh create mode 100755 src/rust-installer/test/rust-installer-v2/gen-install-script.sh create mode 100755 src/rust-installer/test/rust-installer-v2/gen-installer.sh create mode 100644 src/rust-installer/test/rust-installer-v2/install-template.sh create mode 100644 src/rust-installer/test/rust-installer-v2/rust-installer-version create mode 100755 src/rust-installer/test/rust-installer-v2/test.sh create mode 100644 src/rust-installer/test/rust-installer-v2/test/image1/bin/bad-bin create mode 100755 src/rust-installer/test/rust-installer-v2/test/image1/bin/program create mode 100755 src/rust-installer/test/rust-installer-v2/test/image1/bin/program2 create mode 100644 src/rust-installer/test/rust-installer-v2/test/image1/dir-to-install/foo create mode 100644 src/rust-installer/test/rust-installer-v2/test/image1/dir-to-not-install/foo create mode 100644 src/rust-installer/test/rust-installer-v2/test/image1/something-to-install create mode 100644 src/rust-installer/test/rust-installer-v2/test/image1/something-to-not-install create mode 100755 src/rust-installer/test/rust-installer-v2/test/image2/bin/oldprogram create mode 100644 src/rust-installer/test/rust-installer-v2/test/image2/dir-to-install/bar create mode 100644 src/rust-installer/test/rust-installer-v2/test/image2/something-to-install create mode 100755 src/rust-installer/test/rust-installer-v2/test/image3/bin/cargo create mode 100644 src/rust-installer/test/rust-installer-v2/test/image4/baz create mode 100644 src/rust-installer/test/rust-installer-v2/test/image4/dir-to-install/qux/bar create mode 100644 src/rust-installer/test/rust-installer-v2/test/image5/dir-to-install/foo create mode 100644 src/rust-installer/test/rust-installer-v2/test/rust-installer-v1/README.md create mode 100755 src/rust-installer/test/rust-installer-v2/test/rust-installer-v1/gen-install-script.sh create mode 100755 src/rust-installer/test/rust-installer-v2/test/rust-installer-v1/gen-installer.sh create mode 100644 src/rust-installer/test/rust-installer-v2/test/rust-installer-v1/install-template.sh create mode 100644 src/test/codegen/issue-32031.rs create mode 100644 src/test/codegen/issue-32364.rs create mode 100644 src/test/codegen/zip.rs rename src/{libcore/build.rs => test/compile-fail/E0062.rs} (72%) create mode 100644 src/test/compile-fail/E0063.rs create mode 100644 src/test/compile-fail/E0067.rs create mode 100644 src/test/compile-fail/E0069.rs create mode 100644 src/test/compile-fail/E0070.rs create mode 100644 src/test/compile-fail/E0071.rs create mode 100644 src/test/compile-fail/E0072.rs create mode 100644 src/test/compile-fail/E0075.rs create mode 100644 src/test/compile-fail/E0076.rs create mode 100644 src/test/compile-fail/E0077.rs create mode 100644 src/test/compile-fail/E0079.rs create mode 100644 src/test/compile-fail/E0080.rs create mode 100644 src/test/compile-fail/E0081.rs create mode 100644 src/test/compile-fail/E0084.rs create mode 100644 src/test/compile-fail/E0087.rs create mode 100644 src/test/compile-fail/E0088.rs create mode 100644 src/test/compile-fail/E0089.rs create mode 100644 src/test/compile-fail/E0091.rs create mode 100644 src/test/compile-fail/E0092.rs create mode 100644 src/test/compile-fail/E0093.rs create mode 100644 src/test/compile-fail/E0094.rs create mode 100644 src/test/compile-fail/E0101.rs create mode 100644 src/test/compile-fail/E0102.rs create mode 100644 src/test/compile-fail/E0106.rs create mode 100644 src/test/compile-fail/E0107.rs create mode 100644 src/test/compile-fail/E0109.rs create mode 100644 src/test/compile-fail/E0110.rs create mode 100644 src/test/compile-fail/E0116.rs create mode 100644 src/test/compile-fail/E0117.rs rename src/test/compile-fail/{E0024.rs => E0118.rs} (74%) create mode 100644 src/test/compile-fail/E0119.rs create mode 100644 src/test/compile-fail/E0120.rs create mode 100644 src/test/compile-fail/E0121.rs create mode 100644 src/test/compile-fail/E0124.rs create mode 100644 src/test/compile-fail/E0128.rs create mode 100644 src/test/compile-fail/E0130.rs create mode 100644 src/test/compile-fail/E0131.rs create mode 100644 src/test/compile-fail/E0132.rs create mode 100644 src/test/compile-fail/E0133.rs create mode 100644 src/test/compile-fail/E0137.rs create mode 100644 src/test/compile-fail/E0138.rs create mode 100644 src/test/compile-fail/E0152.rs create mode 100644 src/test/compile-fail/E0161.rs create mode 100644 src/test/compile-fail/E0162.rs create mode 100644 src/test/compile-fail/E0163.rs create mode 100644 src/test/compile-fail/E0164.rs create mode 100644 src/test/compile-fail/E0165.rs create mode 100644 src/test/compile-fail/E0166.rs create mode 100644 src/test/compile-fail/E0172.rs create mode 100644 src/test/compile-fail/E0178.rs create mode 100644 src/test/compile-fail/E0184.rs create mode 100644 src/test/compile-fail/E0185.rs create mode 100644 src/test/compile-fail/E0186.rs create mode 100644 src/test/compile-fail/E0191.rs create mode 100644 src/test/compile-fail/E0192.rs create mode 100644 src/test/compile-fail/E0194.rs create mode 100644 src/test/compile-fail/E0195.rs create mode 100644 src/test/compile-fail/E0197.rs create mode 100644 src/test/compile-fail/E0199.rs create mode 100644 src/test/compile-fail/E0200.rs create mode 100644 src/test/compile-fail/associated-types/cache/chrono-scan.rs create mode 100644 src/test/compile-fail/associated-types/cache/elision.rs create mode 100644 src/test/compile-fail/associated-types/cache/project-fn-ret-contravariant.rs create mode 100644 src/test/compile-fail/associated-types/cache/project-fn-ret-invariant.rs create mode 100644 src/test/compile-fail/associated-types/cache/wasm-issue-32330.rs create mode 100644 src/test/compile-fail/auxiliary/recursive_reexports.rs create mode 100644 src/test/compile-fail/bad-format-args.rs create mode 100644 src/test/compile-fail/const-unsized.rs create mode 100644 src/test/compile-fail/hr-subtype.rs create mode 100644 src/test/compile-fail/issue-13727.rs rename src/test/{run-make/dep-info-no-analysis/input.rs => compile-fail/issue-22434.rs} (76%) create mode 100644 src/test/compile-fail/issue-23122-1.rs create mode 100644 src/test/compile-fail/issue-23122-2.rs create mode 100644 src/test/compile-fail/issue-23281.rs create mode 100644 src/test/compile-fail/issue-24424.rs create mode 100644 src/test/compile-fail/issue-24819.rs create mode 100644 src/test/compile-fail/issue-25579.rs create mode 100644 src/test/compile-fail/issue-30240.rs delete mode 100644 src/test/compile-fail/issue-30715.rs create mode 100644 src/test/compile-fail/issue-32086.rs create mode 100644 src/test/compile-fail/issue-32829.rs create mode 100644 src/test/compile-fail/issue-32950.rs create mode 100644 src/test/compile-fail/issue-33293.rs create mode 100644 src/test/compile-fail/issue-33571.rs create mode 100644 src/test/compile-fail/issue-33819.rs create mode 100644 src/test/compile-fail/issue-33876.rs create mode 100644 src/test/compile-fail/issue-34028.rs create mode 100644 src/test/compile-fail/issue-34047.rs create mode 100644 src/test/compile-fail/issue-34171.rs create mode 100644 src/test/compile-fail/issue-34194.rs create mode 100644 src/test/compile-fail/issue-34209.rs create mode 100644 src/test/compile-fail/issue-34334.rs create mode 100644 src/test/compile-fail/issue-34349.rs create mode 100644 src/test/compile-fail/issue-34418.rs create mode 100644 src/test/compile-fail/issue-35044.rs create mode 100644 src/test/compile-fail/label-static.rs create mode 100644 src/test/compile-fail/lifetime-underscore.rs create mode 100644 src/test/compile-fail/macro-expanded-include/file.txt create mode 100644 src/test/compile-fail/macro-expanded-include/foo/mod.rs create mode 100644 src/test/compile-fail/macro-expanded-include/test.rs create mode 100644 src/test/compile-fail/macro-invalid-fragment-spec.rs create mode 100644 src/test/compile-fail/macro-missing-delimiters.rs create mode 100644 src/test/compile-fail/macro-use-scope.rs create mode 100644 src/test/compile-fail/mir-dataflow/README.md create mode 100644 src/test/compile-fail/mir-dataflow/def-inits-1.rs create mode 100644 src/test/compile-fail/mir-dataflow/inits-1.rs create mode 100644 src/test/compile-fail/mir-dataflow/uninits-1.rs create mode 100644 src/test/compile-fail/mir-dataflow/uninits-2.rs create mode 100644 src/test/compile-fail/nested-cfg-attrs.rs create mode 100644 src/test/compile-fail/no-warn-on-field-replace-issue-34101.rs create mode 100644 src/test/compile-fail/pat-slice-old-style.rs create mode 100644 src/test/compile-fail/pat-tuple-bad-type.rs create mode 100644 src/test/compile-fail/pat-tuple-feature-gate.rs create mode 100644 src/test/compile-fail/pat-tuple-overfield.rs create mode 100644 src/test/compile-fail/range_traits-1.rs create mode 100644 src/test/compile-fail/range_traits-2.rs create mode 100644 src/test/compile-fail/range_traits-3.rs create mode 100644 src/test/compile-fail/range_traits-4.rs create mode 100644 src/test/compile-fail/range_traits-5.rs create mode 100644 src/test/compile-fail/range_traits-6.rs create mode 100644 src/test/compile-fail/range_traits-7.rs create mode 100644 src/test/compile-fail/recursive-reexports.rs create mode 100644 src/test/compile-fail/unresolved_static_type_field.rs create mode 100644 src/test/debuginfo/pretty-huge-vec.rs create mode 100644 src/test/debuginfo/pretty-uninitialized-vec.rs create mode 100644 src/test/incremental/struct_add_field.rs create mode 100644 src/test/incremental/struct_change_field_name.rs create mode 100644 src/test/incremental/struct_change_field_type.rs create mode 100644 src/test/incremental/struct_change_field_type_cross_crate/auxiliary/a.rs create mode 100644 src/test/incremental/struct_change_field_type_cross_crate/b.rs create mode 100644 src/test/incremental/struct_change_nothing.rs create mode 100644 src/test/incremental/struct_remove_field.rs create mode 100644 src/test/parse-fail/issue-33455.rs create mode 100644 src/test/parse-fail/issue-33569.rs create mode 100644 src/test/parse-fail/pat-tuple-1.rs create mode 100644 src/test/parse-fail/pat-tuple-2.rs create mode 100644 src/test/parse-fail/pat-tuple-3.rs create mode 100644 src/test/parse-fail/pat-tuple-4.rs create mode 100644 src/test/parse-fail/pat-tuple-5.rs create mode 100644 src/test/parse-fail/pat-tuple-6.rs rename src/test/{run-pass/issue-21350.rs => parse-fail/trait-non-item-macros.rs} (73%) create mode 100644 src/test/pretty/attr-variant-data.rs create mode 100644 src/test/pretty/lifetime.rs create mode 100644 src/test/run-fail/issue-30380.rs delete mode 100644 src/test/run-make/dep-info-no-analysis/Makefile delete mode 100644 src/test/run-make/dep-info-no-analysis/input.dd create mode 100644 src/test/run-make/llvm-phase/Makefile create mode 100644 src/test/run-make/llvm-phase/test.rs create mode 100644 src/test/run-pass/auxiliary/issue34796aux.rs create mode 100644 src/test/run-pass/auxiliary/xcrate_generic_fn_nested_return.rs create mode 100644 src/test/run-pass/const-byte-str-cast.rs create mode 100644 src/test/run-pass/dynamic-drop.rs create mode 100644 src/test/run-pass/exhaustive-bool-match-sanity.rs create mode 100644 src/test/run-pass/hygiene.rs create mode 100644 src/test/run-pass/issue-23477.rs rename src/test/run-pass/{issue-23598.rs => issue-23958.rs} (100%) create mode 100644 src/test/run-pass/issue-30240.rs create mode 100644 src/test/run-pass/issue-30276.rs create mode 100644 src/test/run-pass/issue-32805.rs create mode 100644 src/test/run-pass/issue-33770.rs create mode 100644 src/test/run-pass/issue-34074.rs create mode 100644 src/test/run-pass/issue-34932.rs create mode 100644 src/test/run-pass/issue34796.rs create mode 100644 src/test/run-pass/match-unsized.rs create mode 100644 src/test/run-pass/mir_call_with_associated_type.rs create mode 100644 src/test/run-pass/mir_cast_fn_ret.rs create mode 100644 src/test/run-pass/pat-tuple-1.rs create mode 100644 src/test/run-pass/pat-tuple-2.rs create mode 100644 src/test/run-pass/pat-tuple-3.rs create mode 100644 src/test/run-pass/pat-tuple-4.rs create mode 100644 src/test/run-pass/pat-tuple-5.rs create mode 100644 src/test/run-pass/pat-tuple-6.rs create mode 100644 src/test/run-pass/project-cache-issue-31849.rs create mode 100644 src/test/run-pass/sleep.rs create mode 100644 src/test/run-pass/test-vs-cfg-test.rs create mode 100644 src/test/run-pass/thread-local-syntax.rs create mode 100644 src/test/run-pass/trait-item-inside-macro.rs create mode 100644 src/test/run-pass/xcrate_generic_fn_nested_return.rs create mode 100644 src/test/rustdoc/auxiliary/issue-34274.rs create mode 100644 src/test/rustdoc/auxiliary/src-links-external.rs create mode 100644 src/test/rustdoc/deprecated-impls.rs create mode 100644 src/test/rustdoc/hidden-impls.rs create mode 100644 src/test/rustdoc/hidden-methods.rs create mode 100644 src/test/rustdoc/inline_cross/hidden-use.rs create mode 100644 src/test/rustdoc/inline_local/hidden-use.rs create mode 100644 src/test/rustdoc/issue-34025.rs create mode 100644 src/test/rustdoc/issue-34274.rs create mode 100644 src/test/rustdoc/issue-34423.rs create mode 100644 src/test/rustdoc/issue-34473.rs create mode 100644 src/test/rustdoc/module-impls.rs create mode 100644 src/test/rustdoc/redirect-const.rs create mode 100644 src/test/rustdoc/redirect-rename.rs create mode 100644 src/test/rustdoc/src-links-external.rs rename src/test/{compile-fail => ui/mismatched_types}/issue-26480.rs (72%) create mode 100644 src/test/ui/mismatched_types/issue-26480.stderr diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9d61feef81..6093577078 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -108,7 +108,8 @@ root. There are large number of options accepted by this script to alter the configuration used later in the build process. Some options to note: -- `--enable-debug` - Build a debug version of the compiler (disables optimizations) +- `--enable-debug` - Build a debug version of the compiler (disables optimizations, + which speeds up compilation of stage1 rustc) - `--enable-optimize` - Enable optimizations (can be used with `--enable-debug` to make a debug build with optimizations) - `--disable-valgrind-rpass` - Don't run tests with valgrind @@ -122,10 +123,18 @@ To see a full list of options, run `./configure --help`. Some common make targets are: +- `make tips` - show useful targets, variables and other tips for working with + the build system. - `make rustc-stage1` - build up to (and including) the first stage. For most cases we don't need to build the stage2 compiler, so we can save time by not building it. The stage1 compiler is a fully functioning compiler and (probably) will be enough to determine if your change works as expected. +- `make $host/stage1/bin/rustc` - Where $host is a target triple like x86_64-unknown-linux-gnu. + This will build just rustc, without libstd. This is the fastest way to recompile after + you changed only rustc source code. Note however that the resulting rustc binary + won't have a stdlib to link against by default. You can build libstd once with + `make rustc-stage1`, rustc will pick it up afterwards. libstd is only guaranteed to + work if recompiled, so if there are any issues recompile it. - `make check` - build the full compiler & run all tests (takes a while). This is what gets run by the continuous integration system against your pull request. You should run this before submitting to make sure your tests pass diff --git a/Makefile.in b/Makefile.in index 7425e9bd73..9e87ce1d9e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -62,6 +62,8 @@ # * tidy - Basic style check, show highest rustc error code and # the status of language and lib features # * rustc-stage$(stage) - Only build up to a specific stage +# * $host/stage1/bin/rustc - Only build stage1 rustc, not libstd. For further +# information see "Rust recipes for build system success" below. # # Then mix in some of these environment variables to harness the # ultimate power of The Rust Build System. @@ -93,6 +95,15 @@ # // Modifying libstd? Use this command to run unit tests just on your change # make check-stage1-std NO_REBUILD=1 NO_BENCH=1 # +# // Modifying just rustc? +# // Compile rustc+libstd once +# make rustc-stage1 +# // From now on use this command to rebuild just rustc and reuse the previously built libstd +# // $host is a target triple, eg. x86_64-unknown-linux-gnu +# // The resulting binary is located at $host/stage1/bin/rustc. +# // If there are any issues with libstd recompile it with the command above. +# make $host/stage1/bin/rustc +# # // Added a run-pass test? Use this to test running your test # make check-stage1-rpass TESTNAME=my-shiny-new-test # @@ -266,13 +277,17 @@ endif # CTAGS building ifneq ($(strip $(findstring TAGS.emacs,$(MAKECMDGOALS)) \ - $(findstring TAGS.vi,$(MAKECMDGOALS))),) + $(findstring TAGS.vi,$(MAKECMDGOALS)) \ + $(findstring TAGS.rustc.emacs,$(MAKECMDGOALS)) \ + $(findstring TAGS.rustc.vi,$(MAKECMDGOALS))),) CFG_INFO := $(info cfg: including ctags rules) include $(CFG_SRC_DIR)mk/ctags.mk endif .DEFAULT: - @echo "\n======================================================" + @echo + @echo "======================================================" @echo "== If you need help, run 'make help' or 'make tips' ==" - @echo "======================================================\n" + @echo "======================================================" + @echo exit 1 diff --git a/README.md b/README.md index 4e476b4f35..49236d6b67 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # The Rust Programming Language -This is the main source code repository for [Rust]. It contains the compiler, standard library, -and documentation. +This is the main source code repository for [Rust]. It contains the compiler, +standard library, and documentation. [Rust]: https://www.rust-lang.org @@ -19,6 +19,7 @@ Read ["Installing Rust"] from [The Book]. * `g++` 4.7 or later or `clang++` 3.x * `python` 2.7 (but not 3.x) * GNU `make` 3.81 or later + * `cmake` 2.8.8 or later * `curl` * `git` @@ -63,35 +64,37 @@ build. #### MinGW -[MSYS2](http://msys2.github.io/) can be used to easily build Rust on Windows: +[MSYS2][msys2] can be used to easily build Rust on Windows: -1. Grab the latest MSYS2 installer and go through the installer. +msys2: https://msys2.github.io/ -2. From the MSYS2 terminal, install the `mingw64` toolchain and other required - tools. +1. Grab the latest [MSYS2 installer][msys2] and go through the installer. + +2. Run `mingw32_shell.bat` or `mingw64_shell.bat` from wherever you installed + MSYS2 (i.e. `C:\msys64`), depending on whether you want 32-bit or 64-bit + Rust. (As of the latest version of MSYS2 you have to run `msys2_shell.cmd + -mingw32` or `msys2_shell.cmd -mingw64` from the command line instead) + +3. From this terminal, install the required tools: ```sh # Update package mirrors (may be needed if you have a fresh install of MSYS2) $ pacman -Sy pacman-mirrors - ``` - -Download [MinGW from -here](http://mingw-w64.org/doku.php/download/mingw-builds), and choose the -`version=4.9.x,threads=win32,exceptions=dwarf/seh` flavor when installing. Also, make sure to install to a path without spaces in it. After installing, -add its `bin` directory to your `PATH`. This is due to [#28260](https://github.com/rust-lang/rust/issues/28260), in the future, -installing from pacman should be just fine. - - ``` - # Make git available in MSYS2 (if not already available on path) - $ pacman -S git - $ pacman -S base-devel + # Install build tools needed for Rust. If you're building a 32-bit compiler, + # then replace "x86_64" below with "i686". If you've already got git, python, + # or CMake installed and in PATH you can remove them from this list. Note + # that it is important that the `python2` and `cmake` packages **not** used. + # The build has historically been known to fail with these packages. + $ pacman -S git \ + make \ + diffutils \ + mingw-w64-x86_64-python2 \ + mingw-w64-x86_64-cmake \ + mingw-w64-x86_64-gcc ``` -3. Run `mingw32_shell.bat` or `mingw64_shell.bat` from wherever you installed - MSYS2 (i.e. `C:\msys`), depending on whether you want 32-bit or 64-bit Rust. - -4. Navigate to Rust's source code, configure and build it: +4. Navigate to Rust's source code (or clone it), then configure and build it: ```sh $ ./configure @@ -111,12 +114,25 @@ $ ./configure $ make && make install ``` +#### MSVC with rustbuild + +For those who don't want the hassle of MSYS or MinGW, you can invoke rustbuild +directly. All you need are Python 2, CMake, and Git in your PATH (make sure you +do __not__ use the ones from MSYS!). You'll also need Visual Studio 2013 or +newer with the C++ tools. Then all you need to do is invoke the appropriate +vcvars bat file and kick off rustbuild. + +```bat +CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" +python .\src\bootstrap\bootstrap.py +``` + ## Building Documentation If you’d like to build the documentation, it’s almost the same: ```sh -./configure +$ ./configure $ make docs ``` @@ -151,8 +167,8 @@ Snapshot binaries are currently built and tested on several platforms: You may find that other platforms work, but these are our officially supported build environments that are most likely to work. -Rust currently needs between 600MiB and 1.5GiB to build, depending on platform. If it hits -swap, it will take a very long time to build. +Rust currently needs between 600MiB and 1.5GiB to build, depending on platform. +If it hits swap, it will take a very long time to build. There is more advice about hacking on Rust in [CONTRIBUTING.md]. @@ -189,4 +205,5 @@ Rust is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0), with portions covered by various BSD-like licenses. -See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT), and [COPYRIGHT](COPYRIGHT) for details. +See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT), and +[COPYRIGHT](COPYRIGHT) for details. diff --git a/configure b/configure index d4178963f8..6451b87673 100755 --- a/configure +++ b/configure @@ -133,12 +133,13 @@ probe() { } probe_need() { - local V=$1 probe $* + local V=$1 + shift eval VV=\$$V if [ -z "$VV" ] then - err "needed, but unable to find any of: $*" + err "$V needed, but unable to find any of: $*" fi } @@ -593,12 +594,13 @@ opt docs 1 "build standard library documentation" opt compiler-docs 0 "build compiler documentation" opt optimize-tests 1 "build tests with optimizations" opt debuginfo-tests 0 "build tests with debugger metadata" -opt libcpp 1 "build with llvm with libc++ instead of libstdc++ when using clang" +opt libcpp 1 "build llvm with libc++ instead of libstdc++ when using clang" opt llvm-assertions 0 "build LLVM with assertions" opt debug-assertions 0 "build with debugging assertions" opt fast-make 0 "use .gitmodules as timestamp for submodule deps" opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds" opt local-rust 0 "use an installed rustc rather than downloading a snapshot" +opt local-rebuild 0 "use an installed rustc matching the current version, for rebuilds" opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM" opt rpath 1 "build rpaths into rustc itself" opt stage0-landing-pads 1 "enable landing pads during bootstrap with stage0" @@ -724,7 +726,7 @@ if [ -n "$CFG_ENABLE_ORBIT" ]; then putvar CFG_ENABLE_ORBIT; fi step_msg "looking for build programs" -probe_need CFG_CURLORWGET curl wget +probe_need CFG_CURL curl if [ -z "$CFG_PYTHON_PROVIDED" ]; then probe_need CFG_PYTHON python2.7 python2 python fi @@ -773,6 +775,9 @@ probe CFG_BISON bison probe CFG_GDB gdb probe CFG_LLDB lldb +# For building LLVM +probe_need CFG_CMAKE cmake + # On MacOS X, invoking `javac` pops up a dialog if the JDK is not # installed. Since `javac` is only used if `antlr4` is available, # probe for it only in this case. @@ -847,6 +852,16 @@ then BIN_SUF=.exe fi +# --enable-local-rebuild implies --enable-local-rust too +if [ -n "$CFG_ENABLE_LOCAL_REBUILD" ] +then + if [ -z "$CFG_ENABLE_LOCAL_RUST" ] + then + CFG_ENABLE_LOCAL_RUST=1 + putvar CFG_ENABLE_LOCAL_RUST + fi +fi + if [ -n "$CFG_ENABLE_LOCAL_RUST" ] then system_rustc=$(which rustc) @@ -976,11 +991,11 @@ then LLVM_VERSION=$($LLVM_CONFIG --version) case $LLVM_VERSION in - (3.[6-8]*) + (3.[7-8]*) msg "found ok version of LLVM: $LLVM_VERSION" ;; (*) - err "bad LLVM version: $LLVM_VERSION, need >=3.6" + err "bad LLVM version: $LLVM_VERSION, need >=3.7" ;; esac fi @@ -1163,36 +1178,6 @@ do ;; *-msvc) - # There are some MSYS python builds which will auto-translate - # windows-style paths to MSYS-style paths in Python itself. - # Unfortunately this breaks LLVM's build system as somewhere along - # the line LLVM prints a path into a file from Python and then CMake - # later tries to interpret that path. If Python prints a MSYS path - # and CMake tries to use it as a Windows path, you're gonna have a - # Bad Time. - # - # Consequently here we try to detect when that happens and print an - # error if it does. - if $CFG_PYTHON -c 'import sys; print sys.argv[1]' `pwd` | grep '^/' > /dev/null - then - err " - -python is silently translating windows paths to MSYS paths \ -and the build will fail if this python is used. - -Either an official python install must be used or an \ -alternative python package in MinGW must be used. - -If you are building under msys2 try installing the mingw-w64-x86_64-python2 \ -package instead of python2: - -$ pacman -R python2 && pacman -S mingw-w64-x86_64-python2 -" - fi - - # MSVC requires cmake because that's how we're going to build LLVM - probe_need CFG_CMAKE cmake - # There are three builds of cmake on windows: MSVC, MinGW and Cygwin # The Cygwin build does not have generators for Visual Studio, so # detect that here and error. @@ -1276,6 +1261,36 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake esac done +if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ] +then + # There are some MSYS python builds which will auto-translate + # windows-style paths to MSYS-style paths in Python itself. + # Unfortunately this breaks LLVM's build system as somewhere along + # the line LLVM prints a path into a file from Python and then CMake + # later tries to interpret that path. If Python prints a MSYS path + # and CMake tries to use it as a Windows path, you're gonna have a + # Bad Time. + # + # Consequently here we try to detect when that happens and print an + # error if it does. + if $CFG_PYTHON -c 'import sys; print sys.argv[1]' `pwd` | grep '^/' > /dev/null + then + err " + +python is silently translating windows paths to MSYS paths \ +and the build will fail if this python is used. + +Either an official python install must be used or an \ +alternative python package in MinGW must be used. + +If you are building under msys2 try installing the mingw-w64-x86_64-python2 \ +package instead of python2: + +$ pacman -S mingw-w64-x86_64-python2 +" + fi +fi + if [ -n "$CFG_PERF" ] then HAVE_PERF_LOGFD=`$CFG_PERF stat --log-fd 2>&1 | grep 'unknown option'` @@ -1465,27 +1480,16 @@ do elif [ -z $CFG_LLVM_ROOT ] then LLVM_BUILD_DIR=${CFG_BUILD_DIR}$t/llvm - if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ] - then - LLVM_DBG_OPTS="--enable-debug-symbols --disable-optimized" - # Just use LLVM straight from its build directory to - # avoid 'make install' time - LLVM_INST_DIR=$LLVM_BUILD_DIR/Debug - else - LLVM_DBG_OPTS="--enable-optimized" - LLVM_INST_DIR=$LLVM_BUILD_DIR/Release - fi - if [ -z "$CFG_ENABLE_LLVM_ASSERTIONS" ] - then - LLVM_ASSERTION_OPTS="--disable-assertions" - else - LLVM_ASSERTION_OPTS="--enable-assertions" - - # Apparently even if we request assertions be enabled for MSVC, - # LLVM's CMake build system ignore this and outputs in `Release` - # anyway. - if [ ${is_msvc} -eq 0 ]; then - LLVM_INST_DIR=${LLVM_INST_DIR}+Asserts + LLVM_INST_DIR=$LLVM_BUILD_DIR + # For some crazy reason the MSVC output dir is different than Unix + if [ ${is_msvc} -ne 0 ]; then + if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ] + then + # Just use LLVM straight from its build directory to + # avoid 'make install' time + LLVM_INST_DIR=$LLVM_BUILD_DIR/Debug + else + LLVM_INST_DIR=$LLVM_BUILD_DIR/Release fi fi else @@ -1543,88 +1547,60 @@ do err "can only build LLVM for x86 platforms" ;; esac - CFG_CMAKE_GENERATOR=$generator - putvar CFG_CMAKE_GENERATOR - fi - - if [ ${do_reconfigure} -ne 0 ] && [ ${is_msvc} -ne 0 ] - then - msg "configuring LLVM for $t with cmake" - - CMAKE_ARGS="-DLLVM_INCLUDE_TESTS=OFF" - if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ]; then - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Debug" - else - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release" - fi - if [ -z "$CFG_ENABLE_LLVM_ASSERTIONS" ] - then - CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=OFF" - else - CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=ON" - fi - - msg "configuring LLVM with:" - msg "$CMAKE_ARGS" - - (cd $LLVM_BUILD_DIR && "$CFG_CMAKE" $CFG_LLVM_SRC_DIR \ - -G "$CFG_CMAKE_GENERATOR" \ - $CMAKE_ARGS) - need_ok "LLVM cmake configure failed" + else + generator="Unix Makefiles" fi - - if [ ${do_reconfigure} -ne 0 ] && [ ${is_msvc} -eq 0 ] - then - # LLVM's configure doesn't recognize the new Windows triples yet - gnu_t=$(to_gnu_triple $t) - - msg "configuring LLVM for $gnu_t" - - LLVM_TARGETS="--enable-targets=x86,x86_64,arm,aarch64,mips,powerpc" - LLVM_BUILD="--build=$gnu_t" - LLVM_HOST="--host=$gnu_t" - LLVM_TARGET="--target=$gnu_t" - - # Disable unused LLVM features - LLVM_OPTS="$LLVM_DBG_OPTS $LLVM_ASSERTION_OPTS --disable-docs --enable-bindings=none" - # Disable term-info, linkage of which comes in multiple forms, - # making our snapshots incompatible (#9334) - LLVM_OPTS="$LLVM_OPTS --disable-terminfo" - # Try to have LLVM pull in as few dependencies as possible (#9397) - LLVM_OPTS="$LLVM_OPTS --disable-zlib --disable-libffi" - - # Use win32 native thread/lock apis instead of pthread wrapper. - # (llvm's configure tries to find pthread first, so we have to disable it explicitly.) - # Also note that pthreads works badly on mingw-w64 systems: #8996 - case "$CFG_BUILD" in - (*-windows-gnu) - LLVM_OPTS="$LLVM_OPTS --disable-pthreads" + CFG_CMAKE_GENERATOR=$generator + putvar CFG_CMAKE_GENERATOR + + msg "configuring LLVM for $t" + + LLVM_CFLAGS_32="" + LLVM_CXXFLAGS_32="" + LLVM_LDFLAGS_32="" + LLVM_CFLAGS_64="" + LLVM_CXXFLAGS_64="" + LLVM_LDFLAGS_64="" + + case "$CFG_CC" in + ("ccache clang") + LLVM_CXX_32="ccache" + LLVM_CC_32="ccache" + LLVM_CXX_32_ARG1="clang++" + LLVM_CC_32_ARG1="clang" + LLVM_CFLAGS_32="-Qunused-arguments" + LLVM_CXXFLAGS_32="-Qunused-arguments" + + LLVM_CXX_64="ccache" + LLVM_CC_64="ccache" + LLVM_CXX_64_ARG1="clang++" + LLVM_CC_64_ARG1="clang" + LLVM_CFLAGS_64="-Qunused-arguments" + LLVM_CXXFLAGS_64="-Qunused-arguments" ;; - esac - - case "$CFG_CC" in - ("ccache clang") - LLVM_CXX_32="ccache clang++ -Qunused-arguments" - LLVM_CC_32="ccache clang -Qunused-arguments" - - LLVM_CXX_64="ccache clang++ -Qunused-arguments" - LLVM_CC_64="ccache clang -Qunused-arguments" + ("clang") + LLVM_CXX_32="clang++" + LLVM_CC_32="clang" + LLVM_CFLAGS_32="-Qunused-arguments" + LLVM_CXXFLAGS_32="-Qunused-arguments" + + LLVM_CXX_64="clang++" + LLVM_CC_64="clang" + LLVM_CFLAGS_64="-Qunused-arguments" + LLVM_CXXFLAGS_64="-Qunused-arguments" ;; - ("clang") - LLVM_CXX_32="clang++ -Qunused-arguments" - LLVM_CC_32="clang -Qunused-arguments" - - LLVM_CXX_64="clang++ -Qunused-arguments" - LLVM_CC_64="clang -Qunused-arguments" + ("ccache gcc") + LLVM_CXX_32="ccache" + LLVM_CC_32="ccache" + LLVM_CXX_32_ARG1="clang++" + LLVM_CC_32_ARG1="clang" + + LLVM_CXX_64="ccache" + LLVM_CC_64="ccache" + LLVM_CXX_64_ARG1="g++" + LLVM_CC_64_ARG1="gcc" ;; - ("ccache gcc") - LLVM_CXX_32="ccache g++" - LLVM_CC_32="ccache gcc" - - LLVM_CXX_64="ccache g++" - LLVM_CC_64="ccache gcc" - ;; - ("gcc") + ("gcc") LLVM_CXX_32="g++" LLVM_CC_32="gcc" @@ -1632,7 +1608,7 @@ do LLVM_CC_64="gcc" ;; - (*) + (*) msg "inferring LLVM_CXX/CC from CXX/CC = $CXX/$CC" if [ -n "$CFG_ENABLE_CCACHE" ] then @@ -1641,11 +1617,15 @@ do err "ccache requested but not found" fi - LLVM_CXX_32="ccache $CXX" - LLVM_CC_32="ccache $CC" + LLVM_CXX_32="ccache" + LLVM_CC_32="ccache" + LLVM_CXX_32_ARG1="$CXX" + LLVM_CC_32_ARG1="$CC" - LLVM_CXX_64="ccache $CXX" - LLVM_CC_64="ccache $CC" + LLVM_CXX_64="ccache" + LLVM_CC_64="ccache" + LLVM_CXX_64_ARG1="$CXX" + LLVM_CC_64_ARG1="$CC" else LLVM_CXX_32="$CXX" LLVM_CC_32="$CC" @@ -1655,86 +1635,102 @@ do fi ;; - esac + esac + + case "$CFG_CPUTYPE" in + (x86*) + LLVM_CFLAGS_32="$LLVM_CFLAGS_32 -m32" + LLVM_CXXFLAGS_32="$LLVM_CXXFLAGS_32 -m32" + LLVM_LDFLAGS_32="$LLVM_LDFLAGS_32 -m32" + ;; + esac - case "$CFG_CPUTYPE" in - (x86*) - LLVM_CXX_32="$LLVM_CXX_32 -m32" - LLVM_CC_32="$LLVM_CC_32 -m32" + if echo $t | grep -q x86_64 + then + LLVM_CXX=$LLVM_CXX_64 + LLVM_CC=$LLVM_CC_64 + LLVM_CXX_ARG1=$LLVM_CXX_64_ARG1 + LLVM_CC_ARG1=$LLVM_CC_64_ARG1 + LLVM_CFLAGS=$LLVM_CFLAGS_64 + LLVM_CXXFLAGS=$LLVM_CXXFLAGS_64 + LLVM_LDFLAGS=$LLVM_LDFLAGS_64 + else + LLVM_CXX=$LLVM_CXX_32 + LLVM_CC=$LLVM_CC_32 + LLVM_CXX_ARG1=$LLVM_CXX_32_ARG1 + LLVM_CC_ARG1=$LLVM_CC_32_ARG1 + LLVM_CFLAGS=$LLVM_CFLAGS_32 + LLVM_CXXFLAGS=$LLVM_CXXFLAGS_32 + LLVM_LDFLAGS=$LLVM_LDFLAGS_32 + fi - LLVM_CFLAGS_32="-m32" - LLVM_CXXFLAGS_32="-m32" - LLVM_LDFLAGS_32="-m32" + if [ "$CFG_USING_LIBCPP" != "0" ]; then + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_LIBCXX=ON" + fi - LLVM_CFLAGS_64="" - LLVM_CXXFLAGS_64="" - LLVM_LDFLAGS_64="" + # Turn off things we don't need + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_INCLUDE_TESTS=OFF" + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_INCLUDE_EXAMPLES=OFF" + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_INCLUDE_DOCS=OFF" + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ZLIB=OFF" + CMAKE_ARGS="$CMAKE_ARGS -DWITH_POLY=OFF" + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_TERMINFO=OFF" + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_LIBEDIT=OFF" - LLVM_CXX_32="$LLVM_CXX_32 -m32" - LLVM_CC_32="$LLVM_CC_32 -m32" - ;; + arch="$(echo "$t" | cut -d - -f 1)" - (*) - LLVM_CFLAGS_32="" - LLVM_CXXFLAGS_32="" - LLVM_LDFLAGS_32="" + if [ "$arch" = i686 ]; then + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_BUILD_32_BITS=ON" + fi - LLVM_CFLAGS_64="" - LLVM_CXXFLAGS_64="" - LLVM_LDFLAGS_64="" - ;; - esac + if [ "$t" != "$CFG_BUILD" ]; then + # see http://llvm.org/docs/HowToCrossCompileLLVM.html + CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_CROSSCOMPILING=True" + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGET_ARCH=$arch" + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TABLEGEN=$CFG_BUILD_DIR/$CFG_BUILD/llvm/bin/llvm-tblgen" + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_DEFAULT_TARGET_TRIPLE=$t" + fi - if echo $t | grep -q x86_64 - then - LLVM_CXX=$LLVM_CXX_64 - LLVM_CC=$LLVM_CC_64 - LLVM_CFLAGS=$LLVM_CFLAGS_64 - LLVM_CXXFLAGS=$LLVM_CXXFLAGS_64 - LLVM_LDFLAGS=$LLVM_LDFLAGS_64 - else - LLVM_CXX=$LLVM_CXX_32 - LLVM_CC=$LLVM_CC_32 - LLVM_CFLAGS=$LLVM_CFLAGS_32 - LLVM_CXXFLAGS=$LLVM_CXXFLAGS_32 - LLVM_LDFLAGS=$LLVM_LDFLAGS_32 + # MSVC handles compiler business itself + if [ ${is_msvc} -eq 0 ]; then + CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_C_COMPILER=$LLVM_CC" + CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_CXX_COMPILER=$LLVM_CXX" + CMAKE_ARGS="$CMAKE_ARGS '-DCMAKE_C_FLAGS=$LLVM_CFLAGS'" + CMAKE_ARGS="$CMAKE_ARGS '-DCMAKE_CXX_FLAGS=$LLVM_CXXFLAGS'" + if [ -n "$LLVM_CC_ARG1" ]; then + CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_C_COMPILER_ARG1=$LLVM_CC_ARG1" + fi + if [ -n "$LLVM_CXX_ARG1" ]; then + CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_CXX_COMPILER_ARG1=$LLVM_CXX_ARG1" fi + # FIXME: What about LDFLAGS? + fi - CXX=$LLVM_CXX - CC=$LLVM_CC - CFLAGS="$CFLAGS $LLVM_CFLAGS" - CXXFLAGS="$CXXFLAGS $LLVM_CXXFLAGS" - LDFLAGS="$LDFLAGS $LLVM_LDFLAGS" + if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ]; then + CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Debug" + else + CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release" + fi + if [ -z "$CFG_ENABLE_LLVM_ASSERTIONS" ] + then + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=OFF" + else + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=ON" + fi - if [ "$CFG_USING_LIBCPP" != "0" ]; then - LLVM_OPTS="$LLVM_OPTS --enable-libcpp" - fi + CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64;Mips;PowerPC'" + CMAKE_ARGS="$CMAKE_ARGS -G '$CFG_CMAKE_GENERATOR'" + CMAKE_ARGS="$CMAKE_ARGS $CFG_LLVM_SRC_DIR" - LLVM_FLAGS="$LLVM_TARGETS $LLVM_OPTS $LLVM_BUILD \ - $LLVM_HOST $LLVM_TARGET --with-python=$CFG_PYTHON" + if [ ${do_reconfigure} -ne 0 ] + then + msg "configuring LLVM for $t with cmake" msg "configuring LLVM with:" - msg "$LLVM_FLAGS" - - export CXX - export CC - export CFLAGS - export CXXFLAGS - export LDFLAGS - - cd $LLVM_BUILD_DIR - case $CFG_SRC_DIR in - /* | [a-z]:* | [A-Z]:*) - ${CFG_LLVM_SRC_DIR}configure $LLVM_FLAGS - ;; - *) - ${CFG_BUILD_DIR}${CFG_LLVM_SRC_DIR}configure \ - $LLVM_FLAGS - ;; - esac - need_ok "LLVM configure failed" + msg "$CMAKE_ARGS" - cd $CFG_BUILD_DIR + (cd $LLVM_BUILD_DIR && eval "\"$CFG_CMAKE\"" $CMAKE_ARGS) + need_ok "LLVM cmake configure failed" fi # Construct variables for LLVM build and install directories for diff --git a/mk/cfg/i686-unknown-linux-gnu.mk b/mk/cfg/i686-unknown-linux-gnu.mk index 88c0907f63..129af8ac69 100644 --- a/mk/cfg/i686-unknown-linux-gnu.mk +++ b/mk/cfg/i686-unknown-linux-gnu.mk @@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_i686-unknown-linux-gnu=lib$(1).a CFG_LIB_GLOB_i686-unknown-linux-gnu=lib$(1)-*.so CFG_LIB_DSYM_GLOB_i686-unknown-linux-gnu=lib$(1)-*.dylib.dSYM CFG_JEMALLOC_CFLAGS_i686-unknown-linux-gnu := -m32 $(CFLAGS) -CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS) +CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS) -march=i686 CFG_GCCISH_CXXFLAGS_i686-unknown-linux-gnu := -fno-rtti $(CXXFLAGS) CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32 CFG_GCCISH_DEF_FLAG_i686-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list= diff --git a/mk/cfg/i686-unknown-linux-musl.mk b/mk/cfg/i686-unknown-linux-musl.mk index 4c64402a73..c1cd20a843 100644 --- a/mk/cfg/i686-unknown-linux-musl.mk +++ b/mk/cfg/i686-unknown-linux-musl.mk @@ -1,6 +1,6 @@ # i686-unknown-linux-musl configuration CC_i686-unknown-linux-musl=$(CFG_MUSL_ROOT)/bin/musl-gcc -CXX_i686-unknown-linux-musl=notaprogram +CXX_i686-unknown-linux-musl=$(CXX) CPP_i686-unknown-linux-musl=$(CFG_MUSL_ROOT)/bin/musl-gcc -E AR_i686-unknown-linux-musl=$(AR) CFG_INSTALL_ONLY_RLIB_i686-unknown-linux-musl = 1 diff --git a/mk/cfg/mips-unknown-linux-gnu.mk b/mk/cfg/mips-unknown-linux-gnu.mk index 9e7042befa..0783a4c17a 100644 --- a/mk/cfg/mips-unknown-linux-gnu.mk +++ b/mk/cfg/mips-unknown-linux-gnu.mk @@ -7,10 +7,10 @@ CFG_LIB_NAME_mips-unknown-linux-gnu=lib$(1).so CFG_STATIC_LIB_NAME_mips-unknown-linux-gnu=lib$(1).a CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so CFG_LIB_DSYM_GLOB_mips-unknown-linux-gnu=lib$(1)-*.dylib.dSYM -CFG_JEMALLOC_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 $(CFLAGS) -CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 $(CFLAGS) +CFG_JEMALLOC_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -mabi=32 $(CFLAGS) +CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -mabi=32 $(CFLAGS) CFG_GCCISH_CXXFLAGS_mips-unknown-linux-gnu := -fno-rtti $(CXXFLAGS) -CFG_GCCISH_LINK_FLAGS_mips-unknown-linux-gnu := -shared -fPIC -g -mips32r2 -msoft-float -mabi=32 +CFG_GCCISH_LINK_FLAGS_mips-unknown-linux-gnu := -shared -fPIC -g -mips32r2 -mabi=32 CFG_GCCISH_DEF_FLAG_mips-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list= CFG_LLC_FLAGS_mips-unknown-linux-gnu := CFG_INSTALL_NAME_mips-unknown-linux-gnu = diff --git a/mk/cfg/x86_64-unknown-linux-musl.mk b/mk/cfg/x86_64-unknown-linux-musl.mk index 62a884874b..dfe9de18f5 100644 --- a/mk/cfg/x86_64-unknown-linux-musl.mk +++ b/mk/cfg/x86_64-unknown-linux-musl.mk @@ -1,6 +1,6 @@ # x86_64-unknown-linux-musl configuration CC_x86_64-unknown-linux-musl=$(CFG_MUSL_ROOT)/bin/musl-gcc -CXX_x86_64-unknown-linux-musl=notaprogram +CXX_x86_64-unknown-linux-musl=$(CXX) CPP_x86_64-unknown-linux-musl=$(CFG_MUSL_ROOT)/bin/musl-gcc -E AR_x86_64-unknown-linux-musl=$(AR) CFG_INSTALL_ONLY_RLIB_x86_64-unknown-linux-musl = 1 diff --git a/mk/crates.mk b/mk/crates.mk index 1583515014..0bd0c70bd0 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -57,10 +57,10 @@ TARGET_CRATES := libc std term \ panic_abort panic_unwind unwind RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_driver \ rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \ - rustc_data_structures rustc_platform_intrinsics \ + rustc_data_structures rustc_platform_intrinsics rustc_errors \ rustc_plugin rustc_metadata rustc_passes rustc_save_analysis \ rustc_const_eval rustc_const_math rustc_incremental -HOST_CRATES := syntax syntax_ext $(RUSTC_CRATES) rustdoc fmt_macros \ +HOST_CRATES := syntax syntax_ext syntax_pos $(RUSTC_CRATES) rustdoc fmt_macros \ flate arena graphviz rbml log serialize TOOLS := compiletest rustdoc rustc rustbook error_index_generator @@ -98,43 +98,45 @@ DEPS_serialize := std log DEPS_term := std DEPS_test := std getopts term native:rust_test_helpers -DEPS_syntax := std term serialize log arena libc rustc_bitflags rustc_unicode -DEPS_syntax_ext := syntax fmt_macros +DEPS_syntax := std term serialize log arena libc rustc_bitflags rustc_unicode rustc_errors syntax_pos +DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros +DEPS_syntax_pos := serialize DEPS_rustc_const_math := std syntax log serialize DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize \ - rustc_back graphviz + rustc_back graphviz syntax_pos DEPS_rustc := syntax fmt_macros flate arena serialize getopts rbml \ log graphviz rustc_llvm rustc_back rustc_data_structures\ - rustc_const_math + rustc_const_math syntax_pos rustc_errors DEPS_rustc_back := std syntax flate log libc -DEPS_rustc_borrowck := rustc rustc_mir log graphviz syntax +DEPS_rustc_borrowck := rustc log graphviz syntax syntax_pos rustc_errors rustc_mir DEPS_rustc_data_structures := std log serialize DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \ rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \ rustc_trans rustc_privacy rustc_lint rustc_plugin \ rustc_metadata syntax_ext rustc_passes rustc_save_analysis rustc_const_eval \ - rustc_incremental -DEPS_rustc_lint := rustc log syntax rustc_const_eval + rustc_incremental syntax_pos rustc_errors +DEPS_rustc_errors := log libc serialize syntax_pos +DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags -DEPS_rustc_metadata := rustc syntax rbml rustc_const_math -DEPS_rustc_passes := syntax rustc core rustc_const_eval -DEPS_rustc_mir := rustc syntax rustc_const_math rustc_const_eval rustc_bitflags -DEPS_rustc_resolve := arena rustc log syntax +DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rbml rustc_const_math +DEPS_rustc_passes := syntax syntax_pos rustc core rustc_const_eval rustc_errors +DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags +DEPS_rustc_resolve := arena rustc log syntax syntax_pos rustc_errors DEPS_rustc_platform_intrinsics := std -DEPS_rustc_plugin := rustc rustc_metadata syntax rustc_mir -DEPS_rustc_privacy := rustc log syntax -DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back rustc_mir \ +DEPS_rustc_plugin := rustc rustc_metadata syntax syntax_pos rustc_errors +DEPS_rustc_privacy := rustc log syntax syntax_pos +DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \ log syntax serialize rustc_llvm rustc_platform_intrinsics \ - rustc_const_math rustc_const_eval rustc_incremental -DEPS_rustc_incremental := rbml rustc serialize rustc_data_structures -DEPS_rustc_save_analysis := rustc log syntax serialize -DEPS_rustc_typeck := rustc syntax rustc_platform_intrinsics rustc_const_math \ - rustc_const_eval + rustc_const_math rustc_const_eval rustc_incremental rustc_errors syntax_pos +DEPS_rustc_incremental := rbml rustc syntax_pos serialize rustc_data_structures +DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize +DEPS_rustc_typeck := rustc syntax syntax_pos rustc_platform_intrinsics rustc_const_math \ + rustc_const_eval rustc_errors DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \ - test rustc_lint rustc_const_eval + test rustc_lint rustc_const_eval syntax_pos TOOL_DEPS_compiletest := test getopts log serialize diff --git a/mk/llvm.mk b/mk/llvm.mk index 2bdbef35ba..2298565221 100644 --- a/mk/llvm.mk +++ b/mk/llvm.mk @@ -27,31 +27,36 @@ endif define DEF_LLVM_RULES +ifeq ($(1),$$(CFG_BUILD)) +LLVM_DEPS_TARGET_$(1) := $$(LLVM_DEPS) +else +LLVM_DEPS_TARGET_$(1) := $$(LLVM_DEPS) $$(LLVM_CONFIG_$$(CFG_BUILD)) +endif + # If CFG_LLVM_ROOT is defined then we don't build LLVM ourselves ifeq ($(CFG_LLVM_ROOT),) LLVM_STAMP_$(1) = $$(CFG_LLVM_BUILD_DIR_$(1))/llvm-auto-clean-stamp +LLVM_DONE_$(1) = $$(CFG_LLVM_BUILD_DIR_$(1))/llvm-finished-building -ifeq ($$(findstring msvc,$(1)),msvc) +$$(LLVM_CONFIG_$(1)): $$(LLVM_DONE_$(1)) -$$(LLVM_CONFIG_$(1)): $$(LLVM_DEPS) $$(LLVM_STAMP_$(1)) +$$(LLVM_DONE_$(1)): $$(LLVM_DEPS_TARGET_$(1)) $$(LLVM_STAMP_$(1)) @$$(call E, cmake: llvm) +ifeq ($$(findstring msvc,$(1)),msvc) $$(Q)$$(CFG_CMAKE) --build $$(CFG_LLVM_BUILD_DIR_$(1)) \ --config $$(LLVM_BUILD_CONFIG_MODE) - $$(Q)touch $$(LLVM_CONFIG_$(1)) +else + $$(Q)$$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1)) +endif + $$(Q)touch $$@ +ifeq ($$(findstring msvc,$(1)),msvc) clean-llvm$(1): - else - -$$(LLVM_CONFIG_$(1)): $$(LLVM_DEPS) $$(LLVM_STAMP_$(1)) - @$$(call E, make: llvm) - $$(Q)$$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1)) $$(CFG_LLVM_BUILD_ENV_$(1)) ONLY_TOOLS="$$(LLVM_TOOLS)" - $$(Q)touch $$(LLVM_CONFIG_$(1)) - clean-llvm$(1): + @$$(call E, clean: llvm) $$(Q)$$(MAKE) -C $$(CFG_LLVM_BUILD_DIR_$(1)) clean - endif else diff --git a/mk/main.mk b/mk/main.mk index c47020c9f9..aa70f4a298 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -13,12 +13,12 @@ ###################################################################### # The version number -CFG_RELEASE_NUM=1.10.0 +CFG_RELEASE_NUM=1.11.0 # An optional number to put after the label, e.g. '.2' -> '-beta.2' # NB Make sure it starts with a dot to conform to semver pre-release # versions (section 9) -CFG_PRERELEASE_VERSION=.4 +CFG_PRERELEASE_VERSION=.3 # Append a version-dependent hash to each library, so we can install different # versions in the same place @@ -34,7 +34,14 @@ CFG_FILENAME_EXTRA=$(shell printf '%s' $(CFG_RELEASE)$(CFG_EXTRA_FILENAME) | $(C # intentionally not "secure" by any definition, this is largely just a deterrent # from users enabling unstable features on the stable compiler. CFG_BOOTSTRAP_KEY=$(CFG_FILENAME_EXTRA) + +# The stage0 compiler needs to use the previous key recorded in src/stage0.txt, +# except for local-rebuild when it just uses the same current key. +ifdef CFG_ENABLE_LOCAL_REBUILD +CFG_BOOTSTRAP_KEY_STAGE0=$(CFG_BOOTSTRAP_KEY) +else CFG_BOOTSTRAP_KEY_STAGE0=$(shell grep 'rustc_key' $(S)src/stage0.txt | sed 's/rustc_key: '//) +endif ifeq ($(CFG_RELEASE_CHANNEL),stable) # This is the normal semver version string, e.g. "0.12.0", "0.12.0-nightly" @@ -152,7 +159,7 @@ ifdef CFG_ENABLE_ORBIT endif ifdef SAVE_TEMPS - CFG_RUSTC_FLAGS += --save-temps + CFG_RUSTC_FLAGS += -C save-temps endif ifdef ASM_COMMENTS CFG_RUSTC_FLAGS += -Z asm-comments @@ -526,6 +533,11 @@ ifneq ($(strip $(CFG_BUILD)),$(strip $(3))) CFGFLAG$(1)_T_$(2)_H_$(3) = stage1 RPATH_VAR$(1)_T_$(2)_H_$(3) := $$(TARGET_RPATH_VAR1_T_$(2)_H_$$(CFG_BUILD)) +else +ifdef CFG_ENABLE_LOCAL_REBUILD +# Assume the local-rebuild rustc already has stage1 features too. +CFGFLAG$(1)_T_$(2)_H_$(3) = stage1 +endif endif endif diff --git a/mk/rt.mk b/mk/rt.mk index 6591812280..d0ab3102d7 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -233,35 +233,98 @@ COMPRT_DEPS := $(wildcard \ $(S)src/compiler-rt/*/*/*/*) endif +# compiler-rt's build system is a godawful mess. Here we figure out +# the ridiculous platform-specific values and paths necessary to get +# useful artifacts out of it. + COMPRT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt) COMPRT_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(COMPRT_NAME_$(1)) COMPRT_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/compiler-rt -ifeq ($$(findstring msvc,$(1)),msvc) -$$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS) $$(LLVM_CONFIG_$$(CFG_BUILD)) - @$$(call E, cmake: compiler-rt) - $$(Q)cd "$$(COMPRT_BUILD_DIR_$(1))"; $$(CFG_CMAKE) "$(S)src/compiler-rt" \ - -DCMAKE_BUILD_TYPE=$$(LLVM_BUILD_CONFIG_MODE) \ - -DLLVM_CONFIG_PATH=$$(LLVM_CONFIG_$$(CFG_BUILD)) \ - -G"$$(CFG_CMAKE_GENERATOR)" - $$(Q)$$(CFG_CMAKE) --build "$$(COMPRT_BUILD_DIR_$(1))" \ - --target lib/builtins/builtins \ - --config $$(LLVM_BUILD_CONFIG_MODE) \ - -- //v:m //nologo - $$(Q)cp $$(COMPRT_BUILD_DIR_$(1))/lib/windows/$$(LLVM_BUILD_CONFIG_MODE)/clang_rt.builtins-$$(HOST_$(1)).lib $$@ +COMPRT_ARCH_$(1) := $$(word 1,$$(subst -, ,$(1))) + +# All this is to figure out the path to the compiler-rt bin +ifeq ($$(findstring windows-msvc,$(1)),windows-msvc) +COMPRT_DIR_$(1) := windows/Release +COMPRT_LIB_NAME_$(1) := clang_rt.builtins-$$(patsubst i%86,i386,$$(COMPRT_ARCH_$(1))) +endif + +ifeq ($$(findstring windows-gnu,$(1)),windows-gnu) +COMPRT_DIR_$(1) := windows +COMPRT_LIB_NAME_$(1) := clang_rt.builtins-$$(COMPRT_ARCH_$(1)) +endif + +ifeq ($$(findstring darwin,$(1)),darwin) +COMPRT_DIR_$(1) := builtins +COMPRT_LIB_NAME_$(1) := clang_rt.builtins_$$(patsubst i686,i386,$$(COMPRT_ARCH_$(1)))_osx +endif + +ifeq ($$(findstring ios,$(1)),ios) +COMPRT_DIR_$(1) := builtins +COMPRT_ARCH_$(1) := $$(patsubst armv7s,armv7em,$$(COMPRT_ARCH_$(1))) +COMPRT_LIB_NAME_$(1) := clang_rt.hard_pic_$$(COMPRT_ARCH_$(1))_macho_embedded +ifeq ($$(COMPRT_ARCH_$(1)),aarch64) +COMPRT_LIB_NAME_$(1) := clang_rt.builtins_arm64_ios +endif +COMPRT_DEFINES_$(1) := -DCOMPILER_RT_ENABLE_IOS=ON +endif + +ifndef COMPRT_DIR_$(1) +# NB: FreeBSD and NetBSD output to "linux"... +COMPRT_DIR_$(1) := linux +COMPRT_ARCH_$(1) := $$(patsubst i586,i386,$$(COMPRT_ARCH_$(1))) + +ifeq ($$(findstring android,$(1)),android) +ifeq ($$(findstring arm,$$(COMPRT_ARCH_$(1))),arm) +COMPRT_ARCH_$(1) := armhf +endif +endif + +ifeq ($$(findstring eabihf,$(1)),eabihf) +ifeq ($$(findstring armv7,$(1)),) +COMPRT_LIB_NAME_$(1) := clang_rt.builtins-armhf +endif +endif + +ifndef COMPRT_LIB_NAME_$(1) +COMPRT_LIB_NAME_$(1) := clang_rt.builtins-$$(COMPRT_ARCH_$(1)) +endif +endif + + +ifeq ($$(findstring windows-gnu,$(1)),windows-gnu) +COMPRT_LIB_FILE_$(1) := lib$$(COMPRT_LIB_NAME_$(1)).a +endif + +ifeq ($$(findstring android,$(1)),android) +ifeq ($$(findstring arm,$(1)),arm) +COMPRT_LIB_FILE_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),$$(COMPRT_LIB_NAME_$(1))-android) +endif +endif + +ifndef COMPRT_LIB_FILE_$(1) +COMPRT_LIB_FILE_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),$$(COMPRT_LIB_NAME_$(1))) +endif + +COMPRT_OUTPUT_$(1) := $$(COMPRT_BUILD_DIR_$(1))/lib/$$(COMPRT_DIR_$(1))/$$(COMPRT_LIB_FILE_$(1)) + +ifeq ($$(findstring windows-msvc,$(1)),windows-msvc) +COMPRT_BUILD_ARGS_$(1) := //v:m //nologo +COMPRT_BUILD_TARGET_$(1) := lib/builtins/builtins +COMPRT_BUILD_CC_$(1) := else -COMPRT_CC_$(1) := $$(CC_$(1)) -COMPRT_AR_$(1) := $$(AR_$(1)) -# We chomp -Werror here because GCC warns about the type signature of -# builtins not matching its own and the build fails. It's a bit hacky, -# but what can we do, we're building libclang-rt using GCC ...... -COMPRT_CFLAGS_$(1) := $$(CFG_GCCISH_CFLAGS_$(1)) -Wno-error -std=c99 - -# FreeBSD Clang's packaging is problematic; it doesn't copy unwind.h to -# the standard include directory. This should really be in our changes to -# compiler-rt, but we override the CFLAGS here so there isn't much choice -ifeq ($$(findstring freebsd,$(1)),freebsd) - COMPRT_CFLAGS_$(1) += -I/usr/include/c++/v1 +COMPRT_BUILD_ARGS_$(1) := +ifndef COMPRT_BUILD_TARGET_$(1) +COMPRT_BUILD_TARGET_$(1) := $$(COMPRT_LIB_NAME_$(1)) +endif +COMPRT_BUILD_CC_$(1) := -DCMAKE_C_COMPILER=$$(call FIND_COMPILER,$$(CC_$(1))) \ + -DCMAKE_CXX_COMPILER=$$(call FIND_COMPILER,$$(CXX_$(1))) + +ifeq ($$(findstring ios,$(1)),) +COMPRT_BUILD_CC_$(1) := $$(COMPRT_BUILD_CC_$(1)) \ + -DCMAKE_C_FLAGS="$$(CFG_GCCISH_CFLAGS_$(1)) -Wno-error" +endif + endif ifeq ($$(findstring emscripten,$(1)),emscripten) @@ -273,20 +336,26 @@ $$(COMPRT_LIB_$(1)): else -$$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS) - @$$(call E, make: compiler-rt) - $$(Q)$$(MAKE) -C "$(S)src/compiler-rt" \ - ProjSrcRoot="$(S)src/compiler-rt" \ - ProjObjRoot="$$(abspath $$(COMPRT_BUILD_DIR_$(1)))" \ - CC='$$(COMPRT_CC_$(1))' \ - AR='$$(COMPRT_AR_$(1))' \ - RANLIB='$$(COMPRT_AR_$(1)) s' \ - CFLAGS="$$(COMPRT_CFLAGS_$(1))" \ - TargetTriple=$(1) \ - triple-builtins - $$(Q)cp $$(COMPRT_BUILD_DIR_$(1))/triple/builtins/libcompiler_rt.a $$@ - -endif # if emscripten +$$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS) $$(LLVM_CONFIG_$$(CFG_BUILD)) + @$$(call E, cmake: compiler-rt) + $$(Q)rm -rf $$(COMPRT_BUILD_DIR_$(1)) + $$(Q)mkdir $$(COMPRT_BUILD_DIR_$(1)) + $$(Q)cd "$$(COMPRT_BUILD_DIR_$(1))"; \ + $$(CFG_CMAKE) "$(S)src/compiler-rt" \ + -DCMAKE_BUILD_TYPE=$$(LLVM_BUILD_CONFIG_MODE) \ + -DLLVM_CONFIG_PATH=$$(LLVM_CONFIG_$$(CFG_BUILD)) \ + -DCOMPILER_RT_DEFAULT_TARGET_TRIPLE=$(1) \ + -DCOMPILER_RT_BUILD_SANITIZERS=OFF \ + -DCOMPILER_RT_BUILD_EMUTLS=OFF \ + $$(COMPRT_DEFINES_$(1)) \ + $$(COMPRT_BUILD_CC_$(1)) \ + -G"$$(CFG_CMAKE_GENERATOR)" + $$(Q)$$(CFG_CMAKE) --build "$$(COMPRT_BUILD_DIR_$(1))" \ + --target $$(COMPRT_BUILD_TARGET_$(1)) \ + --config $$(LLVM_BUILD_CONFIG_MODE) \ + -- $$(COMPRT_BUILD_ARGS_$(1)) $$(MFLAGS) + $$(Q)cp "$$(COMPRT_OUTPUT_$(1))" $$@ + endif ################################################################################ @@ -310,20 +379,15 @@ ifeq ($$(findstring darwin,$$(OSTYPE_$(1))),darwin) $$(BACKTRACE_LIB_$(1)): touch $$@ -else -ifeq ($$(findstring ios,$$(OSTYPE_$(1))),ios) +else ifeq ($$(findstring ios,$$(OSTYPE_$(1))),ios) # See comment above $$(BACKTRACE_LIB_$(1)): touch $$@ -else - -ifeq ($$(findstring msvc,$(1)),msvc) +else ifeq ($$(findstring msvc,$(1)),msvc) # See comment above $$(BACKTRACE_LIB_$(1)): touch $$@ -else - -ifeq ($$(findstring emscripten,$(1)),emscripten) +else ifeq ($$(findstring emscripten,$(1)),emscripten) # FIXME: libbacktrace doesn't understand the emscripten triple $$(BACKTRACE_LIB_$(1)): touch $$@ @@ -376,10 +440,7 @@ $$(BACKTRACE_LIB_$(1)): $$(BACKTRACE_BUILD_DIR_$(1))/Makefile $$(MKFILE_DEPS) INCDIR=$(S)src/libbacktrace $$(Q)cp $$(BACKTRACE_BUILD_DIR_$(1))/.libs/libbacktrace.a $$@ -endif # endif for emscripten -endif # endif for msvc -endif # endif for ios -endif # endif for darwin +endif ################################################################################ # libc/libunwind for musl diff --git a/mk/tests.mk b/mk/tests.mk index f9ab84e3f8..ed443147d4 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -276,6 +276,7 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \ check-stage$(1)-T-$(2)-H-$(3)-incremental-exec \ check-stage$(1)-T-$(2)-H-$(3)-ui-exec \ check-stage$(1)-T-$(2)-H-$(3)-doc-exec \ + check-stage$(1)-T-$(2)-H-$(3)-doc-error-index-exec \ check-stage$(1)-T-$(2)-H-$(3)-pretty-exec ifndef CFG_DISABLE_CODEGEN_TESTS diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 942f070c82..57d644d635 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -50,7 +50,7 @@ compiler. What actually happens when you invoke rustbuild is: 1. The entry point script, `src/bootstrap/bootstrap.py` is run. This script is responsible for downloading the stage0 compiler/Cargo binaries, and it then compiles the build system itself (this folder). Finally, it then invokes the - actual `boostrap` binary build system. + actual `bootstrap` binary build system. 2. In Rust, `bootstrap` will slurp up all configuration, perform a number of sanity checks (compilers exist for example), and then start building the stage0 artifacts. diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 0ab5253ee7..33de8fd010 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -10,6 +10,7 @@ import argparse import contextlib +import datetime import hashlib import os import shutil @@ -18,6 +19,8 @@ import sys import tarfile import tempfile +from time import time + def get(url, path, verbose=False): sha_url = url + ".sha256" @@ -30,7 +33,7 @@ def get(url, path, verbose=False): download(sha_path, sha_url, verbose) download(temp_path, url, verbose) verify(temp_path, sha_path, verbose) - print("moving " + temp_path + " to " + path) + print("moving {} to {}".format(temp_path, path)) shutil.move(temp_path, path) finally: delete_if_present(sha_path) @@ -44,7 +47,7 @@ def delete_if_present(path): def download(path, url, verbose): - print("downloading " + url + " to " + path) + print("downloading {} to {}".format(url, path)) # see http://serverfault.com/questions/301128/how-to-download if sys.platform == 'win32': run(["PowerShell.exe", "/nologo", "-Command", @@ -108,14 +111,18 @@ def run(args, verbose=False): def stage0_data(rust_root): nightlies = os.path.join(rust_root, "src/stage0.txt") + data = {} with open(nightlies, 'r') as nightlies: - data = {} - for line in nightlies.read().split("\n"): + for line in nightlies: + line = line.rstrip() # Strip newline character, '\n' if line.startswith("#") or line == '': continue a, b = line.split(": ", 1) data[a] = b - return data + return data + +def format_build_time(duration): + return str(datetime.timedelta(seconds=int(duration))) class RustBuild: def download_stage0(self): @@ -132,20 +139,20 @@ class RustBuild: if os.path.exists(self.bin_root()): shutil.rmtree(self.bin_root()) channel = self.stage0_rustc_channel() - filename = "rust-std-" + channel + "-" + self.build + ".tar.gz" + filename = "rust-std-{}-{}.tar.gz".format(channel, self.build) url = "https://static.rust-lang.org/dist/" + self.stage0_rustc_date() tarball = os.path.join(rustc_cache, filename) if not os.path.exists(tarball): - get(url + "/" + filename, tarball, verbose=self.verbose) + get("{}/{}".format(url, filename), tarball, verbose=self.verbose) unpack(tarball, self.bin_root(), match="rust-std-" + self.build, verbose=self.verbose) - filename = "rustc-" + channel + "-" + self.build + ".tar.gz" + filename = "rustc-{}-{}.tar.gz".format(channel, self.build) url = "https://static.rust-lang.org/dist/" + self.stage0_rustc_date() tarball = os.path.join(rustc_cache, filename) if not os.path.exists(tarball): - get(url + "/" + filename, tarball, verbose=self.verbose) + get("{}/{}".format(url, filename), tarball, verbose=self.verbose) unpack(tarball, self.bin_root(), match="rustc", verbose=self.verbose) with open(self.rustc_stamp(), 'w') as f: f.write(self.stage0_rustc_date()) @@ -153,11 +160,11 @@ class RustBuild: if self.cargo().startswith(self.bin_root()) and \ (not os.path.exists(self.cargo()) or self.cargo_out_of_date()): channel = self.stage0_cargo_channel() - filename = "cargo-" + channel + "-" + self.build + ".tar.gz" + filename = "cargo-{}-{}.tar.gz".format(channel, self.build) url = "https://static.rust-lang.org/cargo-dist/" + self.stage0_cargo_date() tarball = os.path.join(cargo_cache, filename) if not os.path.exists(tarball): - get(url + "/" + filename, tarball, verbose=self.verbose) + get("{}/{}".format(url, filename), tarball, verbose=self.verbose) unpack(tarball, self.bin_root(), match="cargo", verbose=self.verbose) with open(self.cargo_stamp(), 'w') as f: f.write(self.stage0_cargo_date()) @@ -181,13 +188,13 @@ class RustBuild: return os.path.join(self.bin_root(), '.cargo-stamp') def rustc_out_of_date(self): - if not os.path.exists(self.rustc_stamp()): + if not os.path.exists(self.rustc_stamp()) or self.clean: return True with open(self.rustc_stamp(), 'r') as f: return self.stage0_rustc_date() != f.read() def cargo_out_of_date(self): - if not os.path.exists(self.cargo_stamp()): + if not os.path.exists(self.cargo_stamp()) or self.clean: return True with open(self.cargo_stamp(), 'r') as f: return self.stage0_cargo_date() != f.read() @@ -234,8 +241,11 @@ class RustBuild: return '' def build_bootstrap(self): + build_dir = os.path.join(self.build_dir, "bootstrap") + if self.clean and os.path.exists(build_dir): + shutil.rmtree(build_dir) env = os.environ.copy() - env["CARGO_TARGET_DIR"] = os.path.join(self.build_dir, "bootstrap") + env["CARGO_TARGET_DIR"] = build_dir env["RUSTC"] = self.rustc() env["LD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") @@ -246,7 +256,7 @@ class RustBuild: env) def run(self, args, env): - proc = subprocess.Popen(args, env = env) + proc = subprocess.Popen(args, env=env) ret = proc.wait() if ret != 0: sys.exit(ret) @@ -261,20 +271,19 @@ class RustBuild: try: ostype = subprocess.check_output(['uname', '-s']).strip() cputype = subprocess.check_output(['uname', '-m']).strip() - except FileNotFoundError: + except (subprocess.CalledProcessError, WindowsError): if sys.platform == 'win32': return 'x86_64-pc-windows-msvc' - else: - err = "uname not found" - if self.verbose: - raise Exception(err) - sys.exit(err) + err = "uname not found" + if self.verbose: + raise Exception(err) + sys.exit(err) # Darwin's `uname -s` lies and always returns i386. We have to use # sysctl instead. if ostype == 'Darwin' and cputype == 'i686': sysctl = subprocess.check_output(['sysctl', 'hw.optional.x86_64']) - if sysctl.contains(': 1'): + if ': 1' in sysctl: cputype = 'x86_64' # The goal here is to come up with the same triple as LLVM would, @@ -335,11 +344,12 @@ class RustBuild: raise ValueError(err) sys.exit(err) - return cputype + '-' + ostype + return "{}-{}".format(cputype, ostype) def main(): parser = argparse.ArgumentParser(description='Build rust') parser.add_argument('--config') + parser.add_argument('--clean', action='store_true') parser.add_argument('-v', '--verbose', action='store_true') args = [a for a in sys.argv if a != '-h'] @@ -352,6 +362,7 @@ def main(): rb.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) rb.build_dir = os.path.join(os.getcwd(), "build") rb.verbose = args.verbose + rb.clean = args.clean try: with open(args.config or 'config.toml') as config: @@ -367,6 +378,8 @@ def main(): rb._rustc_channel, rb._rustc_date = data['rustc'].split('-', 1) rb._cargo_channel, rb._cargo_date = data['cargo'].split('-', 1) + start_time = time() + # Fetch/build the bootstrap rb.build = rb.build_triple() rb.download_stage0() @@ -385,5 +398,9 @@ def main(): env["BOOTSTRAP_PARENT_ID"] = str(os.getpid()) rb.run(args, env) + end_time = time() + + print("Build completed in %s" % format_build_time(end_time - start_time)) + if __name__ == '__main__': main() diff --git a/src/bootstrap/build/cc.rs b/src/bootstrap/build/cc.rs index d0b0f1007c..ff0941a97d 100644 --- a/src/bootstrap/build/cc.rs +++ b/src/bootstrap/build/cc.rs @@ -57,7 +57,9 @@ pub fn find(build: &mut Build) { let compiler = cfg.get_compiler(); let ar = cc2ar(compiler.path(), target); build.verbose(&format!("CC_{} = {:?}", target, compiler.path())); - build.verbose(&format!("AR_{} = {:?}", target, ar)); + if let Some(ref ar) = ar { + build.verbose(&format!("AR_{} = {:?}", target, ar)); + } build.cc.insert(target.to_string(), (compiler, ar)); } @@ -88,6 +90,7 @@ fn set_compiler(cfg: &mut gcc::Config, // compiler already takes into account the triple in question. t if t.contains("android") => { if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) { + let target = target.replace("armv7", "arm"); let compiler = format!("{}-{}", target, gnu_compiler); cfg.compiler(ndk.join("bin").join(compiler)); } diff --git a/src/bootstrap/build/check.rs b/src/bootstrap/build/check.rs index 154d9556fd..0a096f8e4d 100644 --- a/src/bootstrap/build/check.rs +++ b/src/bootstrap/build/check.rs @@ -23,6 +23,9 @@ use build_helper::output; use bootstrap::{dylib_path, dylib_path_var}; use build::{Build, Compiler, Mode}; +use build::util; + +const ADB_TEST_DIR: &'static str = "/data/tmp"; /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler. /// @@ -88,6 +91,7 @@ pub fn compiletest(build: &Build, target: &str, mode: &str, suite: &str) { + println!("Check compiletest {} ({} -> {})", suite, compiler.host, target); let mut cmd = build.tool_cmd(compiler, "compiletest"); // compiletest currently has... a lot of arguments, so let's just pass all @@ -105,21 +109,23 @@ pub fn compiletest(build: &Build, cmd.arg("--host").arg(compiler.host); cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build)); - let mut flags = format!("-Crpath"); + let mut flags = vec!["-Crpath".to_string()]; if build.config.rust_optimize_tests { - flags.push_str(" -O"); + flags.push("-O".to_string()); } if build.config.rust_debuginfo_tests { - flags.push_str(" -g"); + flags.push("-g".to_string()); } - cmd.arg("--host-rustcflags").arg(&flags); - - let linkflag = format!("-Lnative={}", build.test_helpers_out(target).display()); - cmd.arg("--target-rustcflags").arg(format!("{} {}", flags, linkflag)); + let mut hostflags = build.rustc_flags(&compiler.host); + hostflags.extend(flags.clone()); + cmd.arg("--host-rustcflags").arg(hostflags.join(" ")); - // FIXME: needs android support - cmd.arg("--android-cross-path").arg(""); + let mut targetflags = build.rustc_flags(&target); + targetflags.extend(flags); + targetflags.push(format!("-Lnative={}", + build.test_helpers_out(target).display())); + cmd.arg("--target-rustcflags").arg(targetflags.join(" ")); // FIXME: CFG_PYTHON should probably be detected more robustly elsewhere let python_default = "python"; @@ -180,6 +186,16 @@ pub fn compiletest(build: &Build, } build.add_bootstrap_key(compiler, &mut cmd); + cmd.arg("--adb-path").arg("adb"); + cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR); + if target.contains("android") { + // Assume that cc for this target comes from the android sysroot + cmd.arg("--android-cross-path") + .arg(build.cc(target).parent().unwrap().parent().unwrap()); + } else { + cmd.arg("--android-cross-path").arg(""); + } + build.run(&mut cmd); } @@ -302,7 +318,97 @@ pub fn krate(build: &Build, let mut dylib_path = dylib_path(); dylib_path.insert(0, build.sysroot_libdir(compiler, target)); cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); - cargo.args(&build.flags.args); - build.run(&mut cargo); + if target.contains("android") { + build.run(cargo.arg("--no-run")); + krate_android(build, compiler, target, mode); + } else { + cargo.args(&build.flags.args); + build.run(&mut cargo); + } +} + +fn krate_android(build: &Build, + compiler: &Compiler, + target: &str, + mode: Mode) { + let mut tests = Vec::new(); + let out_dir = build.cargo_out(compiler, mode, target); + find_tests(&out_dir, target, &mut tests); + find_tests(&out_dir.join("deps"), target, &mut tests); + + for test in tests { + build.run(Command::new("adb").arg("push").arg(&test).arg(ADB_TEST_DIR)); + + let test_file_name = test.file_name().unwrap().to_string_lossy(); + let log = format!("{}/check-stage{}-T-{}-H-{}-{}.log", + ADB_TEST_DIR, + compiler.stage, + target, + compiler.host, + test_file_name); + let program = format!("(cd {dir}; \ + LD_LIBRARY_PATH=./{target} ./{test} \ + --logfile {log} \ + {args})", + dir = ADB_TEST_DIR, + target = target, + test = test_file_name, + log = log, + args = build.flags.args.join(" ")); + + let output = output(Command::new("adb").arg("shell").arg(&program)); + println!("{}", output); + build.run(Command::new("adb") + .arg("pull") + .arg(&log) + .arg(build.out.join("tmp"))); + build.run(Command::new("adb").arg("shell").arg("rm").arg(&log)); + if !output.contains("result: ok") { + panic!("some tests failed"); + } + } +} + +fn find_tests(dir: &Path, + target: &str, + dst: &mut Vec) { + for e in t!(dir.read_dir()).map(|e| t!(e)) { + let file_type = t!(e.file_type()); + if !file_type.is_file() { + continue + } + let filename = e.file_name().into_string().unwrap(); + if (target.contains("windows") && filename.ends_with(".exe")) || + (!target.contains("windows") && !filename.contains(".")) { + dst.push(e.path()); + } + } +} + +pub fn android_copy_libs(build: &Build, + compiler: &Compiler, + target: &str) { + println!("Android copy libs to emulator ({})", target); + build.run(Command::new("adb").arg("remount")); + build.run(Command::new("adb").args(&["shell", "rm", "-r", ADB_TEST_DIR])); + build.run(Command::new("adb").args(&["shell", "mkdir", ADB_TEST_DIR])); + build.run(Command::new("adb") + .arg("push") + .arg(build.src.join("src/etc/adb_run_wrapper.sh")) + .arg(ADB_TEST_DIR)); + + let target_dir = format!("{}/{}", ADB_TEST_DIR, target); + build.run(Command::new("adb").args(&["shell", "mkdir", &target_dir[..]])); + + for f in t!(build.sysroot_libdir(compiler, target).read_dir()) { + let f = t!(f); + let name = f.file_name().into_string().unwrap(); + if util::is_dylib(&name) { + build.run(Command::new("adb") + .arg("push") + .arg(f.path()) + .arg(&target_dir)); + } + } } diff --git a/src/bootstrap/build/clean.rs b/src/bootstrap/build/clean.rs index 1d407c9413..91334bdb91 100644 --- a/src/bootstrap/build/clean.rs +++ b/src/bootstrap/build/clean.rs @@ -21,6 +21,9 @@ use std::path::Path; use build::Build; pub fn clean(build: &Build) { + rm_rf(build, "tmp".as_ref()); + rm_rf(build, &build.out.join("tmp")); + for host in build.config.host.iter() { let out = build.out.join(host); diff --git a/src/bootstrap/build/config.rs b/src/bootstrap/build/config.rs index 3c35b9a951..498196e9b6 100644 --- a/src/bootstrap/build/config.rs +++ b/src/bootstrap/build/config.rs @@ -65,8 +65,9 @@ pub struct Config { pub build: String, pub host: Vec, pub target: Vec, - pub rustc: Option, - pub cargo: Option, + pub rustc: Option, + pub cargo: Option, + pub local_rebuild: bool, // libstd features pub debug_jemalloc: bool, @@ -207,8 +208,8 @@ impl Config { config.target.push(target.clone()); } } - config.rustc = build.rustc; - config.cargo = build.cargo; + config.rustc = build.rustc.map(PathBuf::from); + config.cargo = build.cargo.map(PathBuf::from); set(&mut config.compiler_docs, build.compiler_docs); set(&mut config.docs, build.docs); @@ -315,6 +316,7 @@ impl Config { ("RPATH", self.rust_rpath), ("OPTIMIZE_TESTS", self.rust_optimize_tests), ("DEBUGINFO_TESTS", self.rust_debuginfo_tests), + ("LOCAL_REBUILD", self.local_rebuild), } match key { @@ -366,17 +368,21 @@ impl Config { target.ndk = Some(PathBuf::from(value)); } "CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => { - let target = "i686-linux-androideabi".to_string(); + let target = "i686-linux-android".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); target.ndk = Some(PathBuf::from(value)); } "CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => { - let target = "aarch64-linux-androideabi".to_string(); + let target = "aarch64-linux-android".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); target.ndk = Some(PathBuf::from(value)); } + "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { + self.rustc = Some(PathBuf::from(value).join("bin/rustc")); + self.cargo = Some(PathBuf::from(value).join("bin/cargo")); + } _ => {} } } diff --git a/src/bootstrap/build/dist.rs b/src/bootstrap/build/dist.rs index 088e89b658..6eed7eaf20 100644 --- a/src/bootstrap/build/dist.rs +++ b/src/bootstrap/build/dist.rs @@ -135,7 +135,6 @@ pub fn rustc(build: &Build, stage: u32, host: &str) { // Prepare the overlay which is part of the tarball but won't actually be // installed - t!(fs::create_dir_all(&overlay)); let cp = |file: &str| { install(&build.src.join(file), &overlay, 0o644); }; @@ -199,7 +198,6 @@ pub fn rustc(build: &Build, stage: u32, host: &str) { // Copy runtime DLLs needed by the compiler if libdir != "bin" { - t!(fs::create_dir_all(image.join(libdir))); for entry in t!(src.join(libdir).read_dir()).map(|e| t!(e)) { let name = entry.file_name(); if let Some(s) = name.to_str() { @@ -221,7 +219,6 @@ pub fn rustc(build: &Build, stage: u32, host: &str) { let cp = |file: &str| { install(&build.src.join(file), &image.join("share/doc/rust"), 0o644); }; - t!(fs::create_dir_all(&image.join("share/doc/rust"))); cp("COPYRIGHT"); cp("LICENSE-APACHE"); cp("LICENSE-MIT"); @@ -289,6 +286,7 @@ pub fn std(build: &Build, compiler: &Compiler, target: &str) { fn install(src: &Path, dstdir: &Path, perms: u32) { let dst = dstdir.join(src.file_name().unwrap()); + t!(fs::create_dir_all(dstdir)); t!(fs::copy(src, &dst)); chmod(&dst, perms); } diff --git a/src/bootstrap/build/mod.rs b/src/bootstrap/build/mod.rs index ebc05c5f61..195d1bc90c 100644 --- a/src/bootstrap/build/mod.rs +++ b/src/bootstrap/build/mod.rs @@ -119,7 +119,7 @@ pub struct Build { lldb_python_dir: Option, // Runtime state filled in later on - cc: HashMap, + cc: HashMap)>, cxx: HashMap, compiler_rt_built: RefCell>, } @@ -128,6 +128,7 @@ pub struct Build { /// /// These entries currently correspond to the various output directories of the /// build system, with each mod generating output in a different directory. +#[derive(Clone, Copy)] pub enum Mode { /// This cargo is going to build the standard library, placing output in the /// "stageN-std" directory. @@ -383,8 +384,7 @@ impl Build { "ui", "ui"); } CheckDebuginfo { compiler } => { - if target.target.contains("msvc") || - target.target.contains("android") { + if target.target.contains("msvc") { // nothing to do } else if target.target.contains("apple") { check::compiletest(self, &compiler, target.target, @@ -434,8 +434,14 @@ impl Build { target.target); } + AndroidCopyLibs { compiler } => { + check::android_copy_libs(self, &compiler, target.target); + } + + // pseudo-steps Dist { .. } | - Doc { .. } | // pseudo-steps + Doc { .. } | + CheckTarget { .. } | Check { .. } => {} } } @@ -510,6 +516,14 @@ impl Build { .arg("-j").arg(self.jobs().to_string()) .arg("--target").arg(target); + let stage; + if compiler.stage == 0 && self.config.local_rebuild { + // Assume the local-rebuild rustc already has stage1 features. + stage = 1; + } else { + stage = compiler.stage; + } + // Customize the compiler we're running. Specify the compiler to cargo // as our shim and then pass it some various options used to configure // how the actual compiler itself is called. @@ -518,7 +532,7 @@ impl Build { // src/bootstrap/{rustc,rustdoc.rs} cargo.env("RUSTC", self.out.join("bootstrap/debug/rustc")) .env("RUSTC_REAL", self.compiler_path(compiler)) - .env("RUSTC_STAGE", compiler.stage.to_string()) + .env("RUSTC_STAGE", stage.to_string()) .env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string()) .env("RUSTC_CODEGEN_UNITS", self.config.rust_codegen_units.to_string()) @@ -541,7 +555,7 @@ impl Build { // FIXME: the guard against msvc shouldn't need to be here if !target.contains("msvc") { cargo.env(format!("CC_{}", target), self.cc(target)) - .env(format!("AR_{}", target), self.ar(target)) + .env(format!("AR_{}", target), self.ar(target).unwrap()) // only msvc is None .env(format!("CFLAGS_{}", target), self.cflags(target).join(" ")); } @@ -744,7 +758,7 @@ impl Build { // In stage0 we're using a previously released stable compiler, so we // use the stage0 bootstrap key. Otherwise we use our own build's // bootstrap key. - let bootstrap_key = if compiler.is_snapshot(self) { + let bootstrap_key = if compiler.is_snapshot(self) && !self.config.local_rebuild { &self.bootstrap_key_stage0 } else { &self.bootstrap_key @@ -817,8 +831,8 @@ impl Build { } /// Returns the path to the `ar` archive utility for the target specified. - fn ar(&self, target: &str) -> &Path { - &self.cc[target].1 + fn ar(&self, target: &str) -> Option<&Path> { + self.cc[target].1.as_ref().map(|p| &**p) } /// Returns the path to the C++ compiler for the target specified, may panic diff --git a/src/bootstrap/build/native.rs b/src/bootstrap/build/native.rs index 5691b2da6a..f6030cfd09 100644 --- a/src/bootstrap/build/native.rs +++ b/src/bootstrap/build/native.rs @@ -20,14 +20,14 @@ use std::path::Path; use std::process::Command; -use std::fs; +use std::fs::{self, File}; use build_helper::output; use cmake; use gcc; use build::Build; -use build::util::{exe, staticlib, up_to_date}; +use build::util::{staticlib, up_to_date}; /// Compile LLVM for `target`. pub fn llvm(build: &Build, target: &str) { @@ -43,12 +43,14 @@ pub fn llvm(build: &Build, target: &str) { // artifacts are missing) then we keep going, otherwise we bail out. let dst = build.llvm_out(target); let stamp = build.src.join("src/rustllvm/llvm-auto-clean-trigger"); - let llvm_config = dst.join("bin").join(exe("llvm-config", target)); + let done_stamp = dst.join("llvm-finished-building"); build.clear_if_dirty(&dst, &stamp); - if fs::metadata(llvm_config).is_ok() { + if fs::metadata(&done_stamp).is_ok() { return } + println!("Building LLVM for {}", target); + let _ = fs::remove_dir_all(&dst.join("build")); t!(fs::create_dir_all(&dst.join("build"))); let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"}; @@ -111,6 +113,8 @@ pub fn llvm(build: &Build, target: &str) { // tools. Figure out how to filter them down and only build the right // tools and libs on all platforms. cfg.build(); + + t!(File::create(&done_stamp)); } fn check_llvm_version(build: &Build, llvm_config: &Path) { @@ -135,27 +139,66 @@ pub fn compiler_rt(build: &Build, target: &str) { let dst = build.compiler_rt_out(target); let arch = target.split('-').next().unwrap(); let mode = if build.config.rust_optimize {"Release"} else {"Debug"}; + + let build_llvm_config = build.llvm_config(&build.config.build); + let mut cfg = cmake::Config::new(build.src.join("src/compiler-rt")); + cfg.target(target) + .host(&build.config.build) + .out_dir(&dst) + .profile(mode) + .define("LLVM_CONFIG_PATH", build_llvm_config) + .define("COMPILER_RT_DEFAULT_TARGET_TRIPLE", target) + .define("COMPILER_RT_BUILD_SANITIZERS", "OFF") + .define("COMPILER_RT_BUILD_EMUTLS", "OFF") + // inform about c/c++ compilers, the c++ compiler isn't actually used but + // it's needed to get the initial configure to work on all platforms. + .define("CMAKE_C_COMPILER", build.cc(target)) + .define("CMAKE_CXX_COMPILER", build.cc(target)); + let (dir, build_target, libname) = if target.contains("linux") || target.contains("freebsd") || target.contains("netbsd") { - let os = if target.contains("android") {"-android"} else {""}; - let arch = if arch.starts_with("arm") && target.contains("eabihf") { - "armhf" + let os_extra = if target.contains("android") && target.contains("arm") { + "-android" } else { - arch + "" + }; + let builtins_arch = match arch { + "i586" => "i386", + "arm" | "armv7" if target.contains("android") => "armhf", + "arm" if target.contains("eabihf") => "armhf", + _ => arch, + }; + let target = format!("clang_rt.builtins-{}", builtins_arch); + ("linux".to_string(), + target.clone(), + format!("{}{}", target, os_extra)) + } else if target.contains("apple-darwin") { + let builtins_arch = match arch { + "i686" => "i386", + _ => arch, + }; + let target = format!("clang_rt.builtins_{}_osx", builtins_arch); + ("builtins".to_string(), target.clone(), target) + } else if target.contains("apple-ios") { + cfg.define("COMPILER_RT_ENABLE_IOS", "ON"); + let target = match arch { + "armv7s" => "hard_pic_armv7em_macho_embedded".to_string(), + "aarch64" => "builtins_arm64_ios".to_string(), + _ => format!("hard_pic_{}_macho_embedded", arch), }; - let target = format!("clang_rt.builtins-{}{}", arch, os); - ("linux".to_string(), target.clone(), target) - } else if target.contains("darwin") { - let target = format!("clang_rt.builtins_{}_osx", arch); ("builtins".to_string(), target.clone(), target) } else if target.contains("windows-gnu") { let target = format!("clang_rt.builtins-{}", arch); ("windows".to_string(), target.clone(), target) } else if target.contains("windows-msvc") { + let builtins_arch = match arch { + "i586" | "i686" => "i386", + _ => arch, + }; (format!("windows/{}", mode), "lib/builtins/builtins".to_string(), - format!("clang_rt.builtins-{}", arch.replace("i686", "i386"))) + format!("clang_rt.builtins-{}", builtins_arch)) } else { panic!("can't get os from target: {}", target) }; @@ -168,21 +211,7 @@ pub fn compiler_rt(build: &Build, target: &str) { } let _ = fs::remove_dir_all(&dst); t!(fs::create_dir_all(&dst)); - let build_llvm_config = build.llvm_config(&build.config.build); - let mut cfg = cmake::Config::new(build.src.join("src/compiler-rt")); - cfg.target(target) - .host(&build.config.build) - .out_dir(&dst) - .profile(mode) - .define("LLVM_CONFIG_PATH", build_llvm_config) - .define("COMPILER_RT_DEFAULT_TARGET_TRIPLE", target) - .define("COMPILER_RT_BUILD_SANITIZERS", "OFF") - .define("COMPILER_RT_BUILD_EMUTLS", "OFF") - // inform about c/c++ compilers, the c++ compiler isn't actually used but - // it's needed to get the initial configure to work on all platforms. - .define("CMAKE_C_COMPILER", build.cc(target)) - .define("CMAKE_CXX_COMPILER", build.cc(target)) - .build_target(&build_target); + cfg.build_target(&build_target); cfg.build(); } diff --git a/src/bootstrap/build/sanity.rs b/src/bootstrap/build/sanity.rs index a290527742..5eced00e13 100644 --- a/src/bootstrap/build/sanity.rs +++ b/src/bootstrap/build/sanity.rs @@ -70,7 +70,9 @@ pub fn check(build: &mut Build) { // also build some C++ shims for LLVM so we need a C++ compiler. for target in build.config.target.iter() { need_cmd(build.cc(target).as_ref()); - need_cmd(build.ar(target).as_ref()); + if let Some(ar) = build.ar(target) { + need_cmd(ar.as_ref()); + } } for host in build.config.host.iter() { need_cmd(build.cxx(host).as_ref()); @@ -137,6 +139,10 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake "); } } + + if target.contains("arm-linux-android") { + need_cmd("adb".as_ref()); + } } for host in build.flags.host.iter() { diff --git a/src/bootstrap/build/step.rs b/src/bootstrap/build/step.rs index 742fd8575b..7cbbd6740a 100644 --- a/src/bootstrap/build/step.rs +++ b/src/bootstrap/build/step.rs @@ -102,6 +102,7 @@ macro_rules! targets { // Steps for running tests. The 'check' target is just a pseudo // target to depend on a bunch of others. (check, Check { stage: u32, compiler: Compiler<'a> }), + (check_target, CheckTarget { stage: u32, compiler: Compiler<'a> }), (check_linkcheck, CheckLinkcheck { stage: u32 }), (check_cargotest, CheckCargoTest { stage: u32 }), (check_tidy, CheckTidy { stage: u32 }), @@ -138,6 +139,9 @@ macro_rules! targets { (dist_mingw, DistMingw { _dummy: () }), (dist_rustc, DistRustc { stage: u32 }), (dist_std, DistStd { compiler: Compiler<'a> }), + + // Misc targets + (android_copy_libs, AndroidCopyLibs { compiler: Compiler<'a> }), } } } @@ -382,37 +386,80 @@ impl<'a> Step<'a> { self.doc_error_index(stage)] } Source::Check { stage, compiler } => { - vec![ + // Check is just a pseudo step which means check all targets, + // so just depend on checking all targets. + build.config.target.iter().map(|t| { + self.target(t).check_target(stage, compiler) + }).collect() + } + Source::CheckTarget { stage, compiler } => { + // CheckTarget here means run all possible test suites for this + // target. Most of the time, however, we can't actually run + // anything if we're not the build triple as we could be cross + // compiling. + // + // As a result, the base set of targets here is quite stripped + // down from the standard set of targets. These suites have + // their own internal logic to run in cross-compiled situations + // if they'll run at all. For example compiletest knows that + // when testing Android targets we ship artifacts to the + // emulator. + // + // When in doubt the rule of thumb for adding to this list is + // "should this test suite run on the android bot?" + let mut base = vec![ self.check_rpass(compiler), - self.check_rpass_full(compiler), self.check_rfail(compiler), - self.check_rfail_full(compiler), - self.check_cfail(compiler), - self.check_cfail_full(compiler), - self.check_pfail(compiler), - self.check_incremental(compiler), - self.check_ui(compiler), self.check_crate_std(compiler), self.check_crate_test(compiler), - self.check_crate_rustc(compiler), - self.check_codegen(compiler), - self.check_codegen_units(compiler), self.check_debuginfo(compiler), - self.check_rustdoc(compiler), - self.check_pretty(compiler), - self.check_pretty_rpass(compiler), - self.check_pretty_rpass_full(compiler), - self.check_pretty_rfail(compiler), - self.check_pretty_rfail_full(compiler), - self.check_pretty_rpass_valgrind(compiler), - self.check_rpass_valgrind(compiler), - self.check_error_index(compiler), - self.check_docs(compiler), - self.check_rmake(compiler), - self.check_linkcheck(stage), - self.check_tidy(stage), self.dist(stage), - ] + ]; + + // If we're testing the build triple, then we know we can + // actually run binaries and such, so we run all possible tests + // that we know about. + if self.target == build.config.build { + base.extend(vec![ + // docs-related + self.check_docs(compiler), + self.check_error_index(compiler), + self.check_rustdoc(compiler), + + // UI-related + self.check_cfail(compiler), + self.check_pfail(compiler), + self.check_ui(compiler), + + // codegen-related + self.check_incremental(compiler), + self.check_codegen(compiler), + self.check_codegen_units(compiler), + + // misc compiletest-test suites + self.check_rpass_full(compiler), + self.check_rfail_full(compiler), + self.check_cfail_full(compiler), + self.check_pretty_rpass_full(compiler), + self.check_pretty_rfail_full(compiler), + self.check_rpass_valgrind(compiler), + self.check_rmake(compiler), + + // crates + self.check_crate_rustc(compiler), + + // pretty + self.check_pretty(compiler), + self.check_pretty_rpass(compiler), + self.check_pretty_rfail(compiler), + self.check_pretty_rpass_valgrind(compiler), + + // misc + self.check_linkcheck(stage), + self.check_tidy(stage), + ]); + } + return base } Source::CheckLinkcheck { stage } => { vec![self.tool_linkchecker(stage), self.doc(stage)] @@ -437,16 +484,20 @@ impl<'a> Step<'a> { Source::CheckCFail { compiler } | Source::CheckRPassValgrind { compiler } | Source::CheckRPass { compiler } => { - vec![ + let mut base = vec![ self.libtest(compiler), - self.tool_compiletest(compiler.stage), + self.target(compiler.host).tool_compiletest(compiler.stage), self.test_helpers(()), - ] + ]; + if self.target.contains("android") { + base.push(self.android_copy_libs(compiler)); + } + base } Source::CheckDebuginfo { compiler } => { vec![ self.libtest(compiler), - self.tool_compiletest(compiler.stage), + self.target(compiler.host).tool_compiletest(compiler.stage), self.test_helpers(()), self.debugger_scripts(compiler.stage), ] @@ -459,13 +510,14 @@ impl<'a> Step<'a> { Source::CheckPrettyRPassValgrind { compiler } | Source::CheckRMake { compiler } => { vec![self.librustc(compiler), - self.tool_compiletest(compiler.stage)] + self.target(compiler.host).tool_compiletest(compiler.stage)] } Source::CheckDocs { compiler } => { vec![self.libstd(compiler)] } Source::CheckErrorIndex { compiler } => { - vec![self.libstd(compiler), self.tool_error_index(compiler.stage)] + vec![self.libstd(compiler), + self.target(compiler.host).tool_error_index(compiler.stage)] } Source::CheckCrateStd { compiler } => { vec![self.libtest(compiler)] @@ -529,6 +581,10 @@ impl<'a> Step<'a> { } return base } + + Source::AndroidCopyLibs { compiler } => { + vec![self.libtest(compiler)] + } } } } diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 1f3ea8f19b..c657785d78 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -25,6 +25,11 @@ all: clean: $(Q)$(BOOTSTRAP) --clean +rustc-stage1: + $(Q)$(BOOTSTRAP) --step libtest --stage 1 +rustc-stage2: + $(Q)$(BOOTSTRAP) --step libtest --stage 2 + docs: doc doc: $(Q)$(BOOTSTRAP) --step doc diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 8e1da69cf0..838cc4f07a 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -39,9 +39,11 @@ pub fn gnu_target(target: &str) -> String { } } -pub fn cc2ar(cc: &Path, target: &str) -> PathBuf { - if target.contains("musl") || target.contains("msvc") { - PathBuf::from("ar") +pub fn cc2ar(cc: &Path, target: &str) -> Option { + if target.contains("msvc") { + None + } else if target.contains("musl") { + Some(PathBuf::from("ar")) } else { let parent = cc.parent().unwrap(); let file = cc.file_name().unwrap().to_str().unwrap(); @@ -49,10 +51,10 @@ pub fn cc2ar(cc: &Path, target: &str) -> PathBuf { if let Some(idx) = file.rfind(suffix) { let mut file = file[..idx].to_owned(); file.push_str("ar"); - return parent.join(&file); + return Some(parent.join(&file)); } } - parent.join(file) + Some(parent.join(file)) } } diff --git a/src/compiler-rt/CMakeLists.txt b/src/compiler-rt/CMakeLists.txt index 6f0b867463..c60c246efa 100644 --- a/src/compiler-rt/CMakeLists.txt +++ b/src/compiler-rt/CMakeLists.txt @@ -66,8 +66,10 @@ if (NOT COMPILER_RT_STANDALONE_BUILD) # Windows where we need to use clang-cl instead. if(NOT MSVC) set(COMPILER_RT_TEST_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang) + set(COMPILER_RT_TEST_CXX_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++) else() set(COMPILER_RT_TEST_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang.exe) + set(COMPILER_RT_TEST_CXX_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++.exe) endif() else() # Take output dir and install path from the user. @@ -81,6 +83,7 @@ else() option(COMPILER_RT_ENABLE_WERROR "Fail and stop if warning is triggered" OFF) # Use a host compiler to compile/link tests. set(COMPILER_RT_TEST_COMPILER ${CMAKE_C_COMPILER} CACHE PATH "Compiler to use for testing") + set(COMPILER_RT_TEST_CXX_COMPILER ${CMAKE_CXX_COMPILER} CACHE PATH "C++ Compiler to use for testing") if (NOT LLVM_CONFIG_PATH) find_program(LLVM_CONFIG_PATH "llvm-config" @@ -189,6 +192,8 @@ else() endif() option(COMPILER_RT_DEBUG "Build runtimes with full debug info" OFF) +option(COMPILER_RT_EXTERNALIZE_DEBUGINFO + "Generate dSYM files and strip executables and libraries (Darwin Only)" OFF) # COMPILER_RT_DEBUG_PYBOOL is used by lit.common.configured.in. pythonize_bool(COMPILER_RT_DEBUG) @@ -226,6 +231,7 @@ append_list_if(COMPILER_RT_HAS_FUNWIND_TABLES_FLAG -funwind-tables SANITIZER_COM append_list_if(COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG -fno-stack-protector SANITIZER_COMMON_CFLAGS) append_list_if(COMPILER_RT_HAS_FNO_SANITIZE_SAFE_STACK_FLAG -fno-sanitize=safe-stack SANITIZER_COMMON_CFLAGS) append_list_if(COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG -fvisibility=hidden SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_FVISIBILITY_INLINES_HIDDEN_FLAG -fvisibility-inlines-hidden SANITIZER_COMMON_CFLAGS) append_list_if(COMPILER_RT_HAS_FNO_FUNCTION_SECTIONS_FLAG -fno-function-sections SANITIZER_COMMON_CFLAGS) append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto SANITIZER_COMMON_CFLAGS) diff --git a/src/compiler-rt/cmake/Modules/AddCompilerRT.cmake b/src/compiler-rt/cmake/Modules/AddCompilerRT.cmake index 284cf1de70..1ab590e34a 100644 --- a/src/compiler-rt/cmake/Modules/AddCompilerRT.cmake +++ b/src/compiler-rt/cmake/Modules/AddCompilerRT.cmake @@ -19,7 +19,7 @@ function(add_compiler_rt_object_libraries name) set(libname "${name}.${os}") set(libnames ${libnames} ${libname}) set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS}) - list_union(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS) + list_intersect(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS) endforeach() else() foreach(arch ${LIB_ARCHS}) @@ -87,7 +87,7 @@ function(add_compiler_rt_runtime name type) set(libname "${name}_${os}_dynamic") set(extra_linkflags_${libname} ${DARWIN_${os}_LINKFLAGS} ${LIB_LINKFLAGS}) endif() - list_union(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS) + list_intersect(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS) if(LIB_ARCHS_${libname}) list(APPEND libnames ${libname}) set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS} ${LIB_CFLAGS}) @@ -155,6 +155,10 @@ function(add_compiler_rt_runtime name type) set_target_properties(${libname} PROPERTIES OSX_ARCHITECTURES "${LIB_ARCHS_${libname}}") endif() + + if(type STREQUAL "SHARED") + rt_externalize_debuginfo(${libname}) + endif() endforeach() if(LIB_PARENT_TARGET) add_dependencies(${LIB_PARENT_TARGET} ${libnames}) @@ -284,12 +288,14 @@ macro(add_custom_libcxx name prefix) ExternalProject_Add(${name} PREFIX ${prefix} SOURCE_DIR ${COMPILER_RT_LIBCXX_PATH} - CMAKE_ARGS -DCMAKE_C_COMPILER=${COMPILER_RT_TEST_COMPILER} - -DCMAKE_CXX_COMPILER=${COMPILER_RT_TEST_COMPILER} + CMAKE_ARGS -DCMAKE_MAKE_PROGRAM:STRING=${CMAKE_MAKE_PROGRAM} + -DCMAKE_C_COMPILER=${COMPILER_RT_TEST_COMPILER} + -DCMAKE_CXX_COMPILER=${COMPILER_RT_TEST_CXX_COMPILER} -DCMAKE_C_FLAGS=${LIBCXX_CFLAGS} -DCMAKE_CXX_FLAGS=${LIBCXX_CFLAGS} -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH= + -DLLVM_PATH=${LLVM_MAIN_SRC_DIR} LOG_BUILD 1 LOG_CONFIGURE 1 LOG_INSTALL 1 @@ -309,3 +315,24 @@ macro(add_custom_libcxx name prefix) DEPENDS ${LIBCXX_DEPS} ) endmacro() + +function(rt_externalize_debuginfo name) + if(NOT COMPILER_RT_EXTERNALIZE_DEBUGINFO) + return() + endif() + + if(APPLE) + if(CMAKE_CXX_FLAGS MATCHES "-flto" + OR CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE} MATCHES "-flto") + + set(lto_object ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${name}-lto.o) + set_property(TARGET ${name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,-object_path_lto -Wl,${lto_object}") + endif() + add_custom_command(TARGET ${name} POST_BUILD + COMMAND xcrun dsymutil $ + COMMAND xcrun strip -Sl $) + else() + message(FATAL_ERROR "COMPILER_RT_EXTERNALIZE_DEBUGINFO isn't implemented for non-darwin platforms!") + endif() +endfunction() diff --git a/src/compiler-rt/cmake/Modules/CompilerRTCompile.cmake b/src/compiler-rt/cmake/Modules/CompilerRTCompile.cmake index 850d109c26..48f40bf4f7 100644 --- a/src/compiler-rt/cmake/Modules/CompilerRTCompile.cmake +++ b/src/compiler-rt/cmake/Modules/CompilerRTCompile.cmake @@ -24,19 +24,6 @@ function(translate_msvc_cflags out_flags msvc_flags) set(${out_flags} "${clang_flags}" PARENT_SCOPE) endfunction() -if (APPLE) - # On Darwin if /usr/include doesn't exist, the user probably has Xcode but not - # the command line tools. If this is the case, we need to find the OS X - # sysroot to pass to clang. - if(NOT EXISTS /usr/include) - execute_process(COMMAND xcodebuild -version -sdk macosx Path - OUTPUT_VARIABLE OSX_SYSROOT - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - set(OSX_SYSROOT_FLAG "-isysroot${OSX_SYSROOT}") - endif() -endif() - # Compile a source into an object file with COMPILER_RT_TEST_COMPILER using # a provided compile flags and dependenices. # clang_compile( diff --git a/src/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake b/src/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake index c52ba09b8f..d20e372a81 100644 --- a/src/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake +++ b/src/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake @@ -46,6 +46,11 @@ endfunction() # This function takes an OS and a list of architectures and identifies the # subset of the architectures list that the installed toolchain can target. function(darwin_test_archs os valid_archs) + if(${valid_archs}) + message(STATUS "Using cached valid architectures for ${os}.") + return() + endif() + set(archs ${ARGN}) message(STATUS "Finding valid architectures for ${os}...") set(SIMPLE_CPP ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/src.cpp) @@ -73,15 +78,20 @@ function(darwin_test_archs os valid_archs) OUTPUT_VARIABLE TEST_OUTPUT) if(${CAN_TARGET_${os}_${arch}}) list(APPEND working_archs ${arch}) + else() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Testing compiler for supporting ${os}-${arch}:\n" + "${TEST_OUTPUT}\n") endif() endforeach() - set(${valid_archs} ${working_archs} PARENT_SCOPE) + set(${valid_archs} ${working_archs} + CACHE STRING "List of valid architectures for platform ${os}.") endfunction() # This function checks the host cpusubtype to see if it is post-haswell. Haswell # and later machines can run x86_64h binaries. Haswell is cpusubtype 8. function(darwin_filter_host_archs input output) - list_union(tmp_var DARWIN_osx_ARCHS ${input}) + list_intersect(tmp_var DARWIN_osx_ARCHS ${input}) execute_process( COMMAND sysctl hw.cpusubtype OUTPUT_VARIABLE SUBTYPE) @@ -159,11 +169,43 @@ macro(darwin_add_builtin_library name suffix) "PARENT_TARGET;OS;ARCH" "SOURCES;CFLAGS;DEFS" ${ARGN}) + + # --- Workaround --- + # The REF_OS variable was introduced to workaround linking problems when + # compiler-rt is build for the iOS simulator. + # + # Without this workaround, trying to link compiler-rt into an executable for + # the iOS simulator would produce an error like + # + # ld: warning: URGENT: building for iOS simulator, but linking in object + # file built for OSX. Note: This will be an error in the future. + # + # The underlying reason is that the iOS simulator specific configuration is + # stored in variables named like DARWIN_iossim_SYSROOT and not + # DARWIN_macho_embedded_SYSROOT. Thus, with the current setup, compiler-rt + # would be compiled against the OS X SDK and not the iPhone Simulator SDK. + # + # As a workaround we manually override macho_embedded with iossim when + # accessing the DARWIN_*_SYSROOT and DARWIN_*_BUILTIN_MIN_VER_FLAG variables. + # + # This workaround probably break builds of compiler-rt for the watchOS and + # tvOS simulators (if they weren't broken already). + # + # See also rust-lang/rust#34617. + if(${LIB_OS} STREQUAL "macho_embedded") + set(REF_OS iossim) + else() + set(REF_OS ${LIB_OS}) + endif() + set(libname "${name}.${suffix}_${LIB_ARCH}_${LIB_OS}") add_library(${libname} STATIC ${LIB_SOURCES}) + if(DARWIN_${LIB_OS}_SYSROOT) + set(sysroot_flag -isysroot ${DARWIN_${REF_OS}_SYSROOT}) + endif() set_target_compile_flags(${libname} - -isysroot ${DARWIN_${LIB_OS}_SYSROOT} - ${DARWIN_${LIB_OS}_BUILTIN_MIN_VER_FLAG} + ${sysroot_flag} + ${DARWIN_${REF_OS}_BUILTIN_MIN_VER_FLAG} ${LIB_CFLAGS}) set_property(TARGET ${libname} APPEND PROPERTY COMPILE_DEFINITIONS ${LIB_DEFS}) @@ -186,18 +228,22 @@ function(darwin_lipo_libs name) "PARENT_TARGET;OUTPUT_DIR;INSTALL_DIR" "LIPO_FLAGS;DEPENDS" ${ARGN}) - add_custom_command(OUTPUT ${LIB_OUTPUT_DIR}/lib${name}.a - COMMAND ${CMAKE_COMMAND} -E make_directory ${LIB_OUTPUT_DIR} - COMMAND lipo -output - ${LIB_OUTPUT_DIR}/lib${name}.a - -create ${LIB_LIPO_FLAGS} - DEPENDS ${LIB_DEPENDS} - ) - add_custom_target(${name} - DEPENDS ${LIB_OUTPUT_DIR}/lib${name}.a) - add_dependencies(${LIB_PARENT_TARGET} ${name}) - install(FILES ${LIB_OUTPUT_DIR}/lib${name}.a - DESTINATION ${LIB_INSTALL_DIR}) + if(LIB_DEPENDS AND LIB_LIPO_FLAGS) + add_custom_command(OUTPUT ${LIB_OUTPUT_DIR}/lib${name}.a + COMMAND ${CMAKE_COMMAND} -E make_directory ${LIB_OUTPUT_DIR} + COMMAND lipo -output + ${LIB_OUTPUT_DIR}/lib${name}.a + -create ${LIB_LIPO_FLAGS} + DEPENDS ${LIB_DEPENDS} + ) + add_custom_target(${name} + DEPENDS ${LIB_OUTPUT_DIR}/lib${name}.a) + add_dependencies(${LIB_PARENT_TARGET} ${name}) + install(FILES ${LIB_OUTPUT_DIR}/lib${name}.a + DESTINATION ${LIB_INSTALL_DIR}) + else() + message(WARNING "Not generating lipo target for ${name} because no input libraries exist.") + endif() endfunction() # Filter out generic versions of routines that are re-implemented in @@ -220,7 +266,7 @@ function(darwin_filter_builtin_sources output_var exclude_or_include excluded_li list(FIND ${excluded_list} ${_name_we} _found) if(_found ${filter_action} ${filter_value}) list(REMOVE_ITEM intermediate ${_file}) - elseif(${_file} MATCHES ".*/.*\\.S") + elseif(${_file} MATCHES ".*/.*\\.S" OR ${_file} MATCHES ".*/.*\\.c") get_filename_component(_name ${_file} NAME) string(REPLACE ".S" ".c" _cname "${_name}") list(REMOVE_ITEM intermediate ${_cname}) @@ -230,11 +276,18 @@ function(darwin_filter_builtin_sources output_var exclude_or_include excluded_li endfunction() function(darwin_add_eprintf_library) + cmake_parse_arguments(LIB + "" + "" + "CFLAGS" + ${ARGN}) + add_library(clang_rt.eprintf STATIC eprintf.c) set_target_compile_flags(clang_rt.eprintf -isysroot ${DARWIN_osx_SYSROOT} ${DARWIN_osx_BUILTIN_MIN_VER_FLAG} - -arch i386) + -arch i386 + ${LIB_CFLAGS}) set_target_properties(clang_rt.eprintf PROPERTIES OUTPUT_NAME clang_rt.eprintf${COMPILER_RT_OS_SUFFIX}) set_target_properties(clang_rt.eprintf PROPERTIES @@ -251,24 +304,17 @@ endfunction() macro(darwin_add_builtin_libraries) set(DARWIN_EXCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Darwin-excludes) - if(CMAKE_CONFIGURATION_TYPES) - foreach(type ${CMAKE_CONFIGURATION_TYPES}) - set(CMAKE_C_FLAGS_${type} -O3) - set(CMAKE_CXX_FLAGS_${type} -O3) - endforeach() - else() - set(CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE} -O3) - endif() - - set(CMAKE_C_FLAGS "-fPIC -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer") - set(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS}) - set(CMAKE_ASM_FLAGS ${CMAKE_C_FLAGS}) + set(CFLAGS "-fPIC -O3 -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer") + set(CMAKE_C_FLAGS "") + set(CMAKE_CXX_FLAGS "") + set(CMAKE_ASM_FLAGS "") set(PROFILE_SOURCES ../profile/InstrProfiling ../profile/InstrProfilingBuffer - ../profile/InstrProfilingPlatformDarwin) + ../profile/InstrProfilingPlatformDarwin + ../profile/InstrProfilingWriter) foreach (os ${ARGN}) - list_union(DARWIN_BUILTIN_ARCHS DARWIN_${os}_ARCHS BUILTIN_SUPPORTED_ARCH) + list_intersect(DARWIN_BUILTIN_ARCHS DARWIN_${os}_ARCHS BUILTIN_SUPPORTED_ARCH) foreach (arch ${DARWIN_BUILTIN_ARCHS}) darwin_find_excluded_builtins_list(${arch}_${os}_EXCLUDED_BUILTINS OS ${os} @@ -283,7 +329,7 @@ macro(darwin_add_builtin_libraries) OS ${os} ARCH ${arch} SOURCES ${filtered_sources} - CFLAGS -arch ${arch} + CFLAGS ${CFLAGS} -arch ${arch} PARENT_TARGET builtins) endforeach() @@ -306,7 +352,7 @@ macro(darwin_add_builtin_libraries) OS ${os} ARCH ${arch} SOURCES ${filtered_sources} ${PROFILE_SOURCES} - CFLAGS -arch ${arch} -mkernel + CFLAGS ${CFLAGS} -arch ${arch} -mkernel DEFS KERNEL_USE PARENT_TARGET builtins) endforeach() @@ -323,7 +369,7 @@ macro(darwin_add_builtin_libraries) endif() endforeach() - darwin_add_eprintf_library() + darwin_add_eprintf_library(CFLAGS ${CFLAGS}) # We put the x86 sim slices into the archives for their base OS foreach (os ${ARGN}) @@ -339,96 +385,99 @@ macro(darwin_add_builtin_libraries) darwin_add_embedded_builtin_libraries() endmacro() -function(darwin_add_embedded_builtin_libraries) - set(MACHO_SYM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/macho_embedded) - if(CMAKE_CONFIGURATION_TYPES) - foreach(type ${CMAKE_CONFIGURATION_TYPES}) - set(CMAKE_C_FLAGS_${type} -Oz) - set(CMAKE_CXX_FLAGS_${type} -Oz) - endforeach() - else() - set(CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE} -Oz) - endif() +macro(darwin_add_embedded_builtin_libraries) + # this is a hacky opt-out. If you can't target both intel and arm + # architectures we bail here. + set(DARWIN_SOFT_FLOAT_ARCHS armv6m armv7m armv7em armv7) + set(DARWIN_HARD_FLOAT_ARCHS armv7em armv7) + if(COMPILER_RT_SUPPORTED_ARCH MATCHES ".*armv.*") + list(FIND COMPILER_RT_SUPPORTED_ARCH i386 i386_idx) + if(i386_idx GREATER -1) + list(APPEND DARWIN_HARD_FLOAT_ARCHS i386) + endif() - set(CMAKE_C_FLAGS "-Wall -fomit-frame-pointer -ffreestanding") - set(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS}) - set(CMAKE_ASM_FLAGS ${CMAKE_C_FLAGS}) + list(FIND COMPILER_RT_SUPPORTED_ARCH x86_64 x86_64_idx) + if(x86_64_idx GREATER -1) + list(APPEND DARWIN_HARD_FLOAT_ARCHS x86_64) + endif() - set(SOFT_FLOAT_FLAG -mfloat-abi=soft) - set(HARD_FLOAT_FLAG -mfloat-abi=hard) + set(MACHO_SYM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/macho_embedded) - set(PIC_FLAG_ -fPIC) - set(STATIC_FLAG -static) + set(CFLAGS "-Oz -Wall -fomit-frame-pointer -ffreestanding") + set(CMAKE_C_FLAGS "") + set(CMAKE_CXX_FLAGS "") + set(CMAKE_ASM_FLAGS "") - set(DARWIN_macho_embedded_ARCHS armv6m armv7m armv7em armv7 i386 x86_64) + set(SOFT_FLOAT_FLAG -mfloat-abi=soft) + set(HARD_FLOAT_FLAG -mfloat-abi=hard) - set(DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR - ${COMPILER_RT_OUTPUT_DIR}/lib/macho_embedded) - set(DARWIN_macho_embedded_LIBRARY_INSTALL_DIR - ${COMPILER_RT_INSTALL_PATH}/lib/macho_embedded) - - set(CFLAGS_armv7 "-target thumbv7-apple-darwin-eabi") - set(CFLAGS_armv7em "-target thumbv7-apple-darwin-eabi") - set(CFLAGS_armv7m "-target thumbv7-apple-darwin-eabi") - set(CFLAGS_i386 "-march=pentium") + set(ENABLE_PIC Off) + set(PIC_FLAG -fPIC) + set(STATIC_FLAG -static) - set(DARWIN_SOFT_FLOAT_ARCHS armv6m armv7m armv7em armv7) - set(DARWIN_HARD_FLOAT_ARCHS armv7em armv7 i386 x86_64) - - darwin_read_list_from_file(common_FUNCTIONS ${MACHO_SYM_DIR}/common.txt) - darwin_read_list_from_file(thumb2_FUNCTIONS ${MACHO_SYM_DIR}/thumb2.txt) - darwin_read_list_from_file(thumb2_64_FUNCTIONS ${MACHO_SYM_DIR}/thumb2-64.txt) - darwin_read_list_from_file(arm_FUNCTIONS ${MACHO_SYM_DIR}/arm.txt) - darwin_read_list_from_file(i386_FUNCTIONS ${MACHO_SYM_DIR}/i386.txt) - - - set(armv6m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS}) - set(armv7m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS}) - set(armv7em_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS}) - set(armv7_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS} ${thumb2_64_FUNCTIONS}) - set(i386_FUNCTIONS ${common_FUNCTIONS} ${i386_FUNCTIONS}) - set(x86_64_FUNCTIONS ${common_FUNCTIONS}) - - foreach(arch ${DARWIN_macho_embedded_ARCHS}) - darwin_filter_builtin_sources(${arch}_filtered_sources - INCLUDE ${arch}_FUNCTIONS - ${${arch}_SOURCES}) - if(NOT ${arch}_filtered_sources) - message("${arch}_SOURCES: ${${arch}_SOURCES}") - message("${arch}_FUNCTIONS: ${${arch}_FUNCTIONS}") - message(FATAL_ERROR "Empty filtered sources!") - endif() - endforeach() + set(DARWIN_macho_embedded_ARCHS armv6m armv7m armv7em armv7 i386 x86_64) - foreach(float_type SOFT HARD) - foreach(type PIC STATIC) - string(TOLOWER "${float_type}_${type}" lib_suffix) - foreach(arch ${DARWIN_${float_type}_FLOAT_ARCHS}) - set(DARWIN_macho_embedded_SYSROOT ${DARWIN_osx_SYSROOT}) - set(DARWIN_macho_embedded_BUILTIN_MIN_VER_FLAG ${DARWIN_osx_BUILTIN_MIN_VER_FLAG}) - set(float_flag) - if(${arch} MATCHES "^arm") - set(DARWIN_macho_embedded_SYSROOT ${DARWIN_ios_SYSROOT}) - # x86 targets are hard float by default, but the complain about the - # float ABI flag, so don't pass it unless we're targeting arm. - set(float_flag ${${float_type}_FLOAT_FLAG}) - endif() - darwin_add_builtin_library(clang_rt ${lib_suffix} - OS macho_embedded - ARCH ${arch} - SOURCES ${${arch}_filtered_sources} - CFLAGS -arch ${arch} ${${type}_FLAG} ${float_flag} ${CFLAGS_${arch}} - PARENT_TARGET builtins) - endforeach() - foreach(lib ${macho_embedded_${lib_suffix}_libs}) - set_target_properties(${lib} PROPERTIES LINKER_LANGUAGE C) + set(DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR + ${COMPILER_RT_OUTPUT_DIR}/lib/macho_embedded) + set(DARWIN_macho_embedded_LIBRARY_INSTALL_DIR + ${COMPILER_RT_INSTALL_PATH}/lib/macho_embedded) + + set(CFLAGS_armv7 "-target thumbv7-apple-darwin-eabi") + set(CFLAGS_i386 "-march=pentium") + + darwin_read_list_from_file(common_FUNCTIONS ${MACHO_SYM_DIR}/common.txt) + darwin_read_list_from_file(thumb2_FUNCTIONS ${MACHO_SYM_DIR}/thumb2.txt) + darwin_read_list_from_file(thumb2_64_FUNCTIONS ${MACHO_SYM_DIR}/thumb2-64.txt) + darwin_read_list_from_file(arm_FUNCTIONS ${MACHO_SYM_DIR}/arm.txt) + darwin_read_list_from_file(i386_FUNCTIONS ${MACHO_SYM_DIR}/i386.txt) + + + set(armv6m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS}) + set(armv7m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS}) + set(armv7em_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS}) + set(armv7_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS} ${thumb2_64_FUNCTIONS}) + set(i386_FUNCTIONS ${common_FUNCTIONS} ${i386_FUNCTIONS}) + set(x86_64_FUNCTIONS ${common_FUNCTIONS}) + + foreach(arch ${DARWIN_macho_embedded_ARCHS}) + darwin_filter_builtin_sources(${arch}_filtered_sources + INCLUDE ${arch}_FUNCTIONS + ${${arch}_SOURCES}) + if(NOT ${arch}_filtered_sources) + message("${arch}_SOURCES: ${${arch}_SOURCES}") + message("${arch}_FUNCTIONS: ${${arch}_FUNCTIONS}") + message(FATAL_ERROR "Empty filtered sources!") + endif() + endforeach() + + foreach(float_type SOFT HARD) + foreach(type PIC STATIC) + string(TOLOWER "${float_type}_${type}" lib_suffix) + foreach(arch ${DARWIN_${float_type}_FLOAT_ARCHS}) + set(DARWIN_macho_embedded_SYSROOT ${DARWIN_osx_SYSROOT}) + set(float_flag) + if(${arch} MATCHES "^arm") + # x86 targets are hard float by default, but the complain about the + # float ABI flag, so don't pass it unless we're targeting arm. + set(float_flag ${${float_type}_FLOAT_FLAG}) + endif() + darwin_add_builtin_library(clang_rt ${lib_suffix} + OS macho_embedded + ARCH ${arch} + SOURCES ${${arch}_filtered_sources} + CFLAGS ${CFLAGS} -arch ${arch} ${${type}_FLAG} ${float_flag} ${CFLAGS_${arch}} + PARENT_TARGET builtins) + endforeach() + foreach(lib ${macho_embedded_${lib_suffix}_libs}) + set_target_properties(${lib} PROPERTIES LINKER_LANGUAGE C) + endforeach() + darwin_lipo_libs(clang_rt.${lib_suffix} + PARENT_TARGET builtins + LIPO_FLAGS ${macho_embedded_${lib_suffix}_lipo_flags} + DEPENDS ${macho_embedded_${lib_suffix}_libs} + OUTPUT_DIR ${DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR} + INSTALL_DIR ${DARWIN_macho_embedded_LIBRARY_INSTALL_DIR}) endforeach() - darwin_lipo_libs(clang_rt.${lib_suffix} - PARENT_TARGET builtins - LIPO_FLAGS ${macho_embedded_${lib_suffix}_lipo_flags} - DEPENDS ${macho_embedded_${lib_suffix}_libs} - OUTPUT_DIR ${DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR} - INSTALL_DIR ${DARWIN_macho_embedded_LIBRARY_INSTALL_DIR}) endforeach() - endforeach() -endfunction() + endif() +endmacro() diff --git a/src/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/src/compiler-rt/cmake/Modules/CompilerRTUtils.cmake index cf690f4a33..ad9e70c058 100644 --- a/src/compiler-rt/cmake/Modules/CompilerRTUtils.cmake +++ b/src/compiler-rt/cmake/Modules/CompilerRTUtils.cmake @@ -58,7 +58,7 @@ macro(append_have_file_definition filename varname list) list(APPEND ${list} "${varname}=${${varname}}") endmacro() -macro(list_union output input1 input2) +macro(list_intersect output input1 input2) set(${output}) foreach(it ${${input1}}) list(FIND ${input2} ${it} index) diff --git a/src/compiler-rt/cmake/config-ix.cmake b/src/compiler-rt/cmake/config-ix.cmake index 9ede367080..0063cad5d9 100644 --- a/src/compiler-rt/cmake/config-ix.cmake +++ b/src/compiler-rt/cmake/config-ix.cmake @@ -27,7 +27,14 @@ check_cxx_compiler_flag("-Werror -fno-function-sections" COMPILER_RT_HAS_FNO_FUN check_cxx_compiler_flag(-std=c++11 COMPILER_RT_HAS_STD_CXX11_FLAG) check_cxx_compiler_flag(-ftls-model=initial-exec COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC) check_cxx_compiler_flag(-fno-lto COMPILER_RT_HAS_FNO_LTO_FLAG) -check_cxx_compiler_flag(-msse3 COMPILER_RT_HAS_MSSE3_FLAG) +check_cxx_compiler_flag("-Werror -msse3" COMPILER_RT_HAS_MSSE3_FLAG) +check_cxx_compiler_flag(-std=c99 COMPILER_RT_HAS_STD_C99_FLAG) +check_cxx_compiler_flag(--sysroot=. COMPILER_RT_HAS_SYSROOT_FLAG) + +if(NOT WIN32 AND NOT CYGWIN) + # MinGW warns if -fvisibility-inlines-hidden is used. + check_cxx_compiler_flag("-fvisibility-inlines-hidden" COMPILER_RT_HAS_FVISIBILITY_INLINES_HIDDEN_FLAG) +endif() check_cxx_compiler_flag(/GR COMPILER_RT_HAS_GR_FLAG) check_cxx_compiler_flag(/GS COMPILER_RT_HAS_GS_FLAG) @@ -61,7 +68,7 @@ check_cxx_compiler_flag(/wd4800 COMPILER_RT_HAS_WD4800_FLAG) check_symbol_exists(__func__ "" COMPILER_RT_HAS_FUNC_SYMBOL) # Libraries. -check_library_exists(c printf "" COMPILER_RT_HAS_LIBC) +check_library_exists(c fopen "" COMPILER_RT_HAS_LIBC) check_library_exists(dl dlopen "" COMPILER_RT_HAS_LIBDL) check_library_exists(rt shm_open "" COMPILER_RT_HAS_LIBRT) check_library_exists(m pow "" COMPILER_RT_HAS_LIBM) @@ -143,8 +150,11 @@ macro(detect_target_arch) check_symbol_exists(__i386__ "" __I386) check_symbol_exists(__mips__ "" __MIPS) check_symbol_exists(__mips64__ "" __MIPS64) + check_symbol_exists(__wasm32__ "" __WEBASSEMBLY32) + check_symbol_exists(__wasm64__ "" __WEBASSEMBLY64) if(__ARM) - add_default_target_arch(arm) + # Android shouldn't use Thumb2 instructions but can use VFP instructions. + add_default_target_arch(armhf) elseif(__AARCH64) add_default_target_arch(aarch64) elseif(__X86_64) @@ -157,6 +167,10 @@ macro(detect_target_arch) add_default_target_arch(mips64) elseif(__MIPS) add_default_target_arch(mips) + elseif(__WEBASSEMBLY32) + add_default_target_arch(wasm32) + elseif(__WEBASSEMBLY64) + add_default_target_arch(wasm64) endif() endmacro() @@ -191,6 +205,7 @@ elseif(NOT APPLE) # Supported archs for Apple platforms are generated later elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "powerpc") TEST_BIG_ENDIAN(HOST_IS_BIG_ENDIAN) if(HOST_IS_BIG_ENDIAN) + test_target_arch(powerpc "" "-m32") test_target_arch(powerpc64 "" "-m64") else() test_target_arch(powerpc64le "" "-m64") @@ -207,15 +222,21 @@ elseif(NOT APPLE) # Supported archs for Apple platforms are generated later test_target_arch(mips "" "-mips32r2" "--target=mips-linux-gnu") test_target_arch(mips64 "" "-mips64r2" "--target=mips64-linux-gnu" "-mabi=n64") elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "arm") - if("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES "eabihf") - test_target_arch(armhf "" "-march=armv7-a" "-mfloat-abi=hard") + if("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES "armv7") + test_target_arch(armv7 "" "${CMAKE_C_FLAGS}") + elseif("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES "eabihf") + test_target_arch(armhf "" "${CMAKE_C_FLAGS}") else() - test_target_arch(arm "" "-march=armv7-a" "-mfloat-abi=soft") + test_target_arch(arm "" "${CMAKE_C_FLAGS}") endif() elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "aarch32") test_target_arch(aarch32 "" "-march=armv8-a") elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "aarch64") test_target_arch(aarch64 "" "-march=armv8-a") + elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "wasm32") + test_target_arch(wasm32 "" "--target=wasm32-unknown-unknown") + elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "wasm64") + test_target_arch(wasm64 "" "--target=wasm64-unknown-unknown") endif() set(COMPILER_RT_OS_SUFFIX "") endif() @@ -250,12 +271,15 @@ function(get_target_flags_for_arch arch out_var) endfunction() set(ARM64 aarch64) -set(ARM32 arm armhf) +set(ARM32 arm armhf armv7) set(X86 i386 i686) set(X86_64 x86_64) set(MIPS32 mips mipsel) set(MIPS64 mips64 mips64el) +set(PPC powerpc) set(PPC64 powerpc64 powerpc64le) +set(WASM32 wasm32) +set(WASM64 wasm64) if(APPLE) set(ARM64 arm64) @@ -264,7 +288,7 @@ if(APPLE) endif() set(ALL_BUILTIN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} - ${MIPS32} ${MIPS64}) + ${MIPS32} ${MIPS64} ${WASM32} ${WASM64} ${PPC} ${PPC64}) set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64}) set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} @@ -274,19 +298,65 @@ set(ALL_LSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC64} ${MIPS32} ${MIPS64}) -set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) +set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64}) set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64}) -set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64}) +set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64}) +set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64}) if(APPLE) include(CompilerRTDarwinUtils) + # On Darwin if /usr/include doesn't exist, the user probably has Xcode but not + # the command line tools. If this is the case, we need to find the OS X + # sysroot to pass to clang. + if(NOT EXISTS /usr/include) + execute_process(COMMAND xcodebuild -version -sdk macosx Path + OUTPUT_VARIABLE OSX_SYSROOT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(OSX_SYSROOT_FLAG "-isysroot${OSX_SYSROOT}") + endif() + option(COMPILER_RT_ENABLE_IOS "Enable building for iOS - Experimental" Off) + option(COMPILER_RT_ENABLE_WATCHOS "Enable building for watchOS - Experimental" Off) + option(COMPILER_RT_ENABLE_TVOS "Enable building for tvOS - Experimental" Off) find_darwin_sdk_dir(DARWIN_osx_SYSROOT macosx) find_darwin_sdk_dir(DARWIN_iossim_SYSROOT iphonesimulator) find_darwin_sdk_dir(DARWIN_ios_SYSROOT iphoneos) + find_darwin_sdk_dir(DARWIN_watchossim_SYSROOT watchsimulator) + find_darwin_sdk_dir(DARWIN_watchos_SYSROOT watchos) + find_darwin_sdk_dir(DARWIN_tvossim_SYSROOT appletvsimulator) + find_darwin_sdk_dir(DARWIN_tvos_SYSROOT appletvos) + + if(COMPILER_RT_ENABLE_IOS) + list(APPEND DARWIN_EMBEDDED_PLATFORMS ios) + set(DARWIN_ios_MIN_VER_FLAG -miphoneos-version-min) + set(DARWIN_ios_SANITIZER_MIN_VER_FLAG + ${DARWIN_ios_MIN_VER_FLAG}=7.0) + set(DARWIN_ios_BUILTIN_MIN_VER 6.0) + set(DARWIN_ios_BUILTIN_MIN_VER_FLAG + ${DARWIN_ios_MIN_VER_FLAG}=${DARWIN_ios_BUILTIN_MIN_VER}) + endif() + if(COMPILER_RT_ENABLE_WATCHOS) + list(APPEND DARWIN_EMBEDDED_PLATFORMS watchos) + set(DARWIN_watchos_MIN_VER_FLAG -mwatchos-version-min) + set(DARWIN_watchos_SANITIZER_MIN_VER_FLAG + ${DARWIN_watchos_MIN_VER_FLAG}=2.0) + set(DARWIN_watchos_BUILTIN_MIN_VER 2.0) + set(DARWIN_watchos_BUILTIN_MIN_VER_FLAG + ${DARWIN_watchos_MIN_VER_FLAG}=${DARWIN_watchos_BUILTIN_MIN_VER}) + endif() + if(COMPILER_RT_ENABLE_TVOS) + list(APPEND DARWIN_EMBEDDED_PLATFORMS tvos) + set(DARWIN_tvos_MIN_VER_FLAG -mtvos-version-min) + set(DARWIN_tvos_SANITIZER_MIN_VER_FLAG + ${DARWIN_tvos_MIN_VER_FLAG}=9.0) + set(DARWIN_tvos_BUILTIN_MIN_VER 9.0) + set(DARWIN_tvos_BUILTIN_MIN_VER_FLAG + ${DARWIN_tvos_MIN_VER_FLAG}=${DARWIN_tvos_BUILTIN_MIN_VER}) + endif() # Note: In order to target x86_64h on OS X the minimum deployment target must # be 10.8 or higher. @@ -311,13 +381,18 @@ if(APPLE) # We're setting the flag manually for each target OS set(CMAKE_OSX_DEPLOYMENT_TARGET "") - + set(DARWIN_COMMON_CFLAGS -stdlib=libc++) set(DARWIN_COMMON_LINKFLAGS -stdlib=libc++ -lc++ -lc++abi) - + + check_linker_flag("-fapplication-extension" COMPILER_RT_HAS_APP_EXTENSION) + if(COMPILER_RT_HAS_APP_EXTENSION) + list(APPEND DARWIN_COMMON_LINKFLAGS "-fapplication-extension") + endif() + set(DARWIN_osx_CFLAGS ${DARWIN_COMMON_CFLAGS} -mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION}) @@ -336,7 +411,7 @@ if(APPLE) # Figure out which arches to use for each OS darwin_get_toolchain_supported_archs(toolchain_arches) message(STATUS "Toolchain supported arches: ${toolchain_arches}") - + if(NOT MACOSX_VERSION_MIN_FLAG) darwin_test_archs(osx DARWIN_osx_ARCHS @@ -363,98 +438,102 @@ if(APPLE) list(APPEND BUILTIN_SUPPORTED_OS 10.4) endif() - if(DARWIN_iossim_SYSROOT) - set(DARWIN_iossim_CFLAGS - ${DARWIN_COMMON_CFLAGS} - -mios-simulator-version-min=7.0 - -isysroot ${DARWIN_iossim_SYSROOT}) - set(DARWIN_iossim_LINKFLAGS - ${DARWIN_COMMON_LINKFLAGS} - -mios-simulator-version-min=7.0 - -isysroot ${DARWIN_iossim_SYSROOT}) - set(DARWIN_iossim_BUILTIN_MIN_VER 6.0) - set(DARWIN_iossim_BUILTIN_MIN_VER_FLAG - -mios-simulator-version-min=${DARWIN_iossim_BUILTIN_MIN_VER}) - - set(DARWIN_iossim_SKIP_CC_KEXT On) - darwin_test_archs(iossim - DARWIN_iossim_ARCHS - ${toolchain_arches}) - message(STATUS "iOS Simulator supported arches: ${DARWIN_iossim_ARCHS}") - if(DARWIN_iossim_ARCHS) - list(APPEND SANITIZER_COMMON_SUPPORTED_OS iossim) + foreach(platform ${DARWIN_EMBEDDED_PLATFORMS}) + if(DARWIN_${platform}sim_SYSROOT) + set(DARWIN_${platform}sim_CFLAGS + ${DARWIN_COMMON_CFLAGS} + ${DARWIN_${platform}_SANITIZER_MIN_VER_FLAG} + -isysroot ${DARWIN_iossim_SYSROOT}) + set(DARWIN_${platform}sim_LINKFLAGS + ${DARWIN_COMMON_LINKFLAGS} + ${DARWIN_${platform}_SANITIZER_MIN_VER_FLAG} + -isysroot ${DARWIN_${platform}sim_SYSROOT}) + set(DARWIN_${platform}sim_BUILTIN_MIN_VER + ${DARWIN_${platform}_BUILTIN_MIN_VER}) + set(DARWIN_${platform}sim_BUILTIN_MIN_VER_FLAG + ${DARWIN_${platform}_BUILTIN_MIN_VER_FLAG}) + + set(DARWIN_${platform}sim_SKIP_CC_KEXT On) + darwin_test_archs(${platform}sim + DARWIN_${platform}sim_ARCHS + ${toolchain_arches}) + message(STATUS "${platform} Simulator supported arches: ${DARWIN_${platform}sim_ARCHS}") + if(DARWIN_iossim_ARCHS) + list(APPEND SANITIZER_COMMON_SUPPORTED_OS ${platform}sim) + list(APPEND BUILTIN_SUPPORTED_OS ${platform}sim) + list(APPEND PROFILE_SUPPORTED_OS ${platform}sim) + endif() + foreach(arch ${DARWIN_${platform}sim_ARCHS}) + list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch}) + set(CAN_TARGET_${arch} 1) + endforeach() endif() - foreach(arch ${DARWIN_iossim_ARCHS}) - list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch}) - set(CAN_TARGET_${arch} 1) - endforeach() - endif() - if(DARWIN_ios_SYSROOT AND COMPILER_RT_ENABLE_IOS) - set(DARWIN_ios_CFLAGS - ${DARWIN_COMMON_CFLAGS} - -miphoneos-version-min=7.0 - -isysroot ${DARWIN_ios_SYSROOT}) - set(DARWIN_ios_LINKFLAGS - ${DARWIN_COMMON_LINKFLAGS} - -miphoneos-version-min=7.0 - -isysroot ${DARWIN_ios_SYSROOT}) - set(DARWIN_ios_BUILTIN_MIN_VER 6.0) - set(DARWIN_ios_BUILTIN_MIN_VER_FLAG - -miphoneos-version-min=${DARWIN_ios_BUILTIN_MIN_VER}) - - darwin_test_archs(ios - DARWIN_ios_ARCHS - ${toolchain_arches}) - message(STATUS "iOS supported arches: ${DARWIN_ios_ARCHS}") - if(DARWIN_ios_ARCHS) - list(APPEND SANITIZER_COMMON_SUPPORTED_OS ios) - list(APPEND BUILTIN_SUPPORTED_OS ios) - list(APPEND PROFILE_SUPPORTED_OS ios) - list(APPEND BUILTIN_SUPPORTED_OS iossim) + if(DARWIN_${platform}_SYSROOT) + set(DARWIN_${platform}_CFLAGS + ${DARWIN_COMMON_CFLAGS} + ${DARWIN_${platform}_SANITIZER_MIN_VER_FLAG} + -isysroot ${DARWIN_${platform}_SYSROOT}) + set(DARWIN_${platform}_LINKFLAGS + ${DARWIN_COMMON_LINKFLAGS} + ${DARWIN_${platform}_SANITIZER_MIN_VER_FLAG} + -isysroot ${DARWIN_${platform}_SYSROOT}) + + darwin_test_archs(${platform} + DARWIN_${platform}_ARCHS + ${toolchain_arches}) + message(STATUS "${platform} supported arches: ${DARWIN_${platform}_ARCHS}") + if(DARWIN_${platform}_ARCHS) + list(APPEND SANITIZER_COMMON_SUPPORTED_OS ${platform}) + list(APPEND BUILTIN_SUPPORTED_OS ${platform}) + list(APPEND PROFILE_SUPPORTED_OS ${platform}) + endif() + foreach(arch ${DARWIN_${platform}_ARCHS}) + list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch}) + set(CAN_TARGET_${arch} 1) + endforeach() endif() - foreach(arch ${DARWIN_ios_ARCHS}) - list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch}) - set(CAN_TARGET_${arch} 1) - endforeach() - endif() + endforeach() endif() - # for list_union + # for list_intersect include(CompilerRTUtils) - list_union(BUILTIN_SUPPORTED_ARCH ALL_BUILTIN_SUPPORTED_ARCH toolchain_arches) + list_intersect(BUILTIN_SUPPORTED_ARCH ALL_BUILTIN_SUPPORTED_ARCH toolchain_arches) - list_union(SANITIZER_COMMON_SUPPORTED_ARCH + list_intersect(SANITIZER_COMMON_SUPPORTED_ARCH ALL_SANITIZER_COMMON_SUPPORTED_ARCH COMPILER_RT_SUPPORTED_ARCH ) set(LSAN_COMMON_SUPPORTED_ARCH ${SANITIZER_COMMON_SUPPORTED_ARCH}) set(UBSAN_COMMON_SUPPORTED_ARCH ${SANITIZER_COMMON_SUPPORTED_ARCH}) - list_union(ASAN_SUPPORTED_ARCH + list_intersect(ASAN_SUPPORTED_ARCH ALL_ASAN_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) - list_union(DFSAN_SUPPORTED_ARCH + list_intersect(DFSAN_SUPPORTED_ARCH ALL_DFSAN_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) - list_union(LSAN_SUPPORTED_ARCH + list_intersect(LSAN_SUPPORTED_ARCH ALL_LSAN_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) - list_union(MSAN_SUPPORTED_ARCH + list_intersect(MSAN_SUPPORTED_ARCH ALL_MSAN_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) - list_union(PROFILE_SUPPORTED_ARCH + list_intersect(PROFILE_SUPPORTED_ARCH ALL_PROFILE_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) - list_union(TSAN_SUPPORTED_ARCH + list_intersect(TSAN_SUPPORTED_ARCH ALL_TSAN_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) - list_union(UBSAN_SUPPORTED_ARCH + list_intersect(UBSAN_SUPPORTED_ARCH ALL_UBSAN_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) - list_union(SAFESTACK_SUPPORTED_ARCH + list_intersect(SAFESTACK_SUPPORTED_ARCH ALL_SAFESTACK_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) + list_intersect(CFI_SUPPORTED_ARCH + ALL_CFI_SUPPORTED_ARCH + SANITIZER_COMMON_SUPPORTED_ARCH) else() # Architectures supported by compiler-rt libraries. filter_available_targets(BUILTIN_SUPPORTED_ARCH @@ -476,6 +555,7 @@ else() filter_available_targets(UBSAN_SUPPORTED_ARCH ${ALL_UBSAN_SUPPORTED_ARCH}) filter_available_targets(SAFESTACK_SUPPORTED_ARCH ${ALL_SAFESTACK_SUPPORTED_ARCH}) + filter_available_targets(CFI_SUPPORTED_ARCH ${ALL_CFI_SUPPORTED_ARCH}) endif() message(STATUS "Compiler-RT supported architectures: ${COMPILER_RT_SUPPORTED_ARCH}") @@ -538,26 +618,19 @@ else() endif() if (PROFILE_SUPPORTED_ARCH AND - OS_NAME MATCHES "Darwin|Linux|FreeBSD") + OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows") set(COMPILER_RT_HAS_PROFILE TRUE) else() set(COMPILER_RT_HAS_PROFILE FALSE) endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux|FreeBSD") + OS_NAME MATCHES "Darwin|Linux|FreeBSD") set(COMPILER_RT_HAS_TSAN TRUE) else() set(COMPILER_RT_HAS_TSAN FALSE) endif() -if(APPLE) - option(COMPILER_RT_ENABLE_TSAN_OSX "Enable building TSan for OS X - Experimental" Off) - if(COMPILER_RT_ENABLE_TSAN_OSX) - set(COMPILER_RT_HAS_TSAN TRUE) - endif() -endif() - if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows") set(COMPILER_RT_HAS_UBSAN TRUE) @@ -565,17 +638,16 @@ else() set(COMPILER_RT_HAS_UBSAN FALSE) endif() -# -msse3 flag is not valid for Mips therefore clang gives a warning -# message with -msse3. But check_c_compiler_flags() checks only for -# compiler error messages. Therefore COMPILER_RT_HAS_MSSE3_FLAG turns out to be -# true on Mips, so we make it false here. -if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "mips") - set(COMPILER_RT_HAS_MSSE3_FLAG FALSE) -endif() - if (COMPILER_RT_HAS_SANITIZER_COMMON AND SAFESTACK_SUPPORTED_ARCH AND OS_NAME MATCHES "Darwin|Linux|FreeBSD") set(COMPILER_RT_HAS_SAFESTACK TRUE) else() set(COMPILER_RT_HAS_SAFESTACK FALSE) endif() + +if (COMPILER_RT_HAS_SANITIZER_COMMON AND CFI_SUPPORTED_ARCH AND + OS_NAME MATCHES "Linux") + set(COMPILER_RT_HAS_CFI TRUE) +else() + set(COMPILER_RT_HAS_CFI FALSE) +endif() diff --git a/src/compiler-rt/include/sanitizer/common_interface_defs.h b/src/compiler-rt/include/sanitizer/common_interface_defs.h index b736ed9e52..b2a4bb7b89 100644 --- a/src/compiler-rt/include/sanitizer/common_interface_defs.h +++ b/src/compiler-rt/include/sanitizer/common_interface_defs.h @@ -125,9 +125,11 @@ extern "C" { // to know what is being passed to libc functions, e.g. memcmp. // FIXME: implement more hooks. void __sanitizer_weak_hook_memcmp(void *called_pc, const void *s1, - const void *s2, size_t n); + const void *s2, size_t n, int result); void __sanitizer_weak_hook_strncmp(void *called_pc, const char *s1, - const char *s2, size_t n); + const char *s2, size_t n, int result); + void __sanitizer_weak_hook_strcmp(void *called_pc, const char *s1, + const char *s2, int result); #ifdef __cplusplus } // extern "C" #endif diff --git a/src/compiler-rt/include/sanitizer/coverage_interface.h b/src/compiler-rt/include/sanitizer/coverage_interface.h index b93111b859..2dcc09fc84 100644 --- a/src/compiler-rt/include/sanitizer/coverage_interface.h +++ b/src/compiler-rt/include/sanitizer/coverage_interface.h @@ -41,6 +41,13 @@ extern "C" { // Some of the entries in *data will be zero. uintptr_t __sanitizer_get_coverage_guards(uintptr_t **data); + // Set *data to the growing buffer with covered PCs and return the size + // of the buffer. The entries are never zero. + // When only unique pcs are collected, the size is equal to + // __sanitizer_get_total_unique_coverage. + // WARNING: EXPERIMENTAL API. + uintptr_t __sanitizer_get_coverage_pc_buffer(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. diff --git a/src/compiler-rt/lib/CMakeLists.txt b/src/compiler-rt/lib/CMakeLists.txt index 9215b080b7..4bc6f7a2d5 100644 --- a/src/compiler-rt/lib/CMakeLists.txt +++ b/src/compiler-rt/lib/CMakeLists.txt @@ -19,8 +19,6 @@ if(COMPILER_RT_BUILD_SANITIZERS) add_subdirectory(ubsan) endif() - add_subdirectory(cfi) - if(COMPILER_RT_HAS_ASAN) add_subdirectory(asan) endif() @@ -45,4 +43,8 @@ if(COMPILER_RT_BUILD_SANITIZERS) if(COMPILER_RT_HAS_SAFESTACK) add_subdirectory(safestack) endif() + + if(COMPILER_RT_HAS_CFI) + add_subdirectory(cfi) + endif() endif() diff --git a/src/compiler-rt/lib/asan/.clang-format b/src/compiler-rt/lib/asan/.clang-format new file mode 100644 index 0000000000..f6cb8ad931 --- /dev/null +++ b/src/compiler-rt/lib/asan/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: Google diff --git a/src/compiler-rt/lib/asan/README.txt b/src/compiler-rt/lib/asan/README.txt index 8cc9bb17b5..bb6ff42c5c 100644 --- a/src/compiler-rt/lib/asan/README.txt +++ b/src/compiler-rt/lib/asan/README.txt @@ -23,4 +23,4 @@ from the root of your CMake build tree: make check-asan For more instructions see: -http://code.google.com/p/address-sanitizer/wiki/HowToBuild +https://github.com/google/sanitizers/wiki/AddressSanitizerHowToBuild diff --git a/src/compiler-rt/lib/asan/asan_activation.cc b/src/compiler-rt/lib/asan/asan_activation.cc index 1d3582c168..9df3b977ea 100644 --- a/src/compiler-rt/lib/asan/asan_activation.cc +++ b/src/compiler-rt/lib/asan/asan_activation.cc @@ -61,11 +61,6 @@ static struct AsanDeactivatedFlags { parser.ParseString(env); } - // Override from getprop asan.options. - char buf[100]; - GetExtraActivationFlags(buf, sizeof(buf)); - parser.ParseString(buf); - SetVerbosity(cf.verbosity); if (Verbosity()) ReportUnrecognizedFlags(); diff --git a/src/compiler-rt/lib/asan/asan_flags.cc b/src/compiler-rt/lib/asan/asan_flags.cc index 18e597ffa0..363ee67e77 100644 --- a/src/compiler-rt/lib/asan/asan_flags.cc +++ b/src/compiler-rt/lib/asan/asan_flags.cc @@ -116,14 +116,6 @@ void InitializeFlags() { ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS")); #endif - // Let activation flags override current settings. On Android they come - // from a system property. On other platforms this is no-op. - if (!flags()->start_deactivated) { - char buf[100]; - GetExtraActivationFlags(buf, sizeof(buf)); - asan_parser.ParseString(buf); - } - SetVerbosity(common_flags()->verbosity); // TODO(eugenis): dump all flags at verbosity>=2? diff --git a/src/compiler-rt/lib/asan/asan_flags.inc b/src/compiler-rt/lib/asan/asan_flags.inc index ec6400e864..5e69242fb8 100644 --- a/src/compiler-rt/lib/asan/asan_flags.inc +++ b/src/compiler-rt/lib/asan/asan_flags.inc @@ -44,9 +44,6 @@ ASAN_FLAG( "to find more errors.") ASAN_FLAG(bool, replace_intrin, true, "If set, uses custom wrappers for memset/memcpy/memmove intinsics.") -ASAN_FLAG(bool, mac_ignore_invalid_free, false, - "Ignore invalid free() calls to work around some bugs. Used on OS X " - "only.") ASAN_FLAG(bool, detect_stack_use_after_return, false, "Enables stack-use-after-return checking at run-time.") ASAN_FLAG(int, min_uar_stack_size_log, 16, // We can't do smaller anyway. @@ -75,6 +72,7 @@ ASAN_FLAG(bool, check_malloc_usable_size, true, "295.*.") ASAN_FLAG(bool, unmap_shadow_on_exit, false, "If set, explicitly unmaps the (huge) shadow at exit.") +ASAN_FLAG(bool, protect_shadow_gap, true, "If set, mprotect the shadow gap") ASAN_FLAG(bool, print_stats, false, "Print various statistics after printing an error message or if " "atexit=1.") @@ -98,8 +96,8 @@ ASAN_FLAG(bool, poison_array_cookie, true, "Poison (or not) the array cookie after operator new[].") // Turn off alloc/dealloc mismatch checker on Mac and Windows for now. -// https://code.google.com/p/address-sanitizer/issues/detail?id=131 -// https://code.google.com/p/address-sanitizer/issues/detail?id=309 +// https://github.com/google/sanitizers/issues/131 +// https://github.com/google/sanitizers/issues/309 // TODO(glider,timurrrr): Fix known issues and enable this back. ASAN_FLAG(bool, alloc_dealloc_mismatch, (SANITIZER_MAC == 0) && (SANITIZER_WINDOWS == 0), @@ -125,8 +123,8 @@ ASAN_FLAG( "The bigger the value the harder we try.") ASAN_FLAG( bool, detect_container_overflow, true, - "If true, honor the container overflow annotations. " - "See https://code.google.com/p/address-sanitizer/wiki/ContainerOverflow") + "If true, honor the container overflow annotations. See " + "https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow") ASAN_FLAG(int, detect_odr_violation, 2, "If >=2, detect violation of One-Definition-Rule (ODR); " "If ==1, detect ODR-violation only if the two variables " @@ -134,3 +132,6 @@ ASAN_FLAG(int, detect_odr_violation, 2, ASAN_FLAG(bool, dump_instruction_bytes, false, "If true, dump 16 bytes starting at the instruction that caused SEGV") ASAN_FLAG(const char *, suppressions, "", "Suppressions file name.") +ASAN_FLAG(bool, halt_on_error, true, + "Crash the program after printing the first error report " + "(WARNING: USE AT YOUR OWN RISK!)") diff --git a/src/compiler-rt/lib/asan/asan_interceptors.cc b/src/compiler-rt/lib/asan/asan_interceptors.cc index 86879e424a..d9a0c71a00 100644 --- a/src/compiler-rt/lib/asan/asan_interceptors.cc +++ b/src/compiler-rt/lib/asan/asan_interceptors.cc @@ -75,7 +75,7 @@ struct AsanInterceptorContext { } \ if (!suppressed) { \ GET_CURRENT_PC_BP_SP; \ - __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0); \ + ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false);\ } \ } \ } while (0) @@ -178,7 +178,7 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) } while (false) #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) // Strict init-order checking is dlopen-hostile: -// https://code.google.com/p/address-sanitizer/issues/detail?id=178 +// https://github.com/google/sanitizers/issues/178 #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \ if (flags()->strict_init_order) { \ StopInitOrderChecking(); \ diff --git a/src/compiler-rt/lib/asan/asan_interface_internal.h b/src/compiler-rt/lib/asan/asan_interface_internal.h index 18cd2b6dec..9efddcbd42 100644 --- a/src/compiler-rt/lib/asan/asan_interface_internal.h +++ b/src/compiler-rt/lib/asan/asan_interface_internal.h @@ -167,6 +167,19 @@ 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_load1_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_load2_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_load4_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_load8_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_load16_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_store1_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_store2_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_store4_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_store8_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_store16_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN_noabort(uptr p, uptr size); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN_noabort(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); diff --git a/src/compiler-rt/lib/asan/asan_internal.h b/src/compiler-rt/lib/asan/asan_internal.h index 9e9175879f..0ef0d0eb52 100644 --- a/src/compiler-rt/lib/asan/asan_internal.h +++ b/src/compiler-rt/lib/asan/asan_internal.h @@ -75,8 +75,6 @@ void AsanCheckIncompatibleRT(); void AsanOnDeadlySignal(int, void *siginfo, void *context); -void DisableReexec(); -void MaybeReexec(); void ReadContextStack(void *context, uptr *stack, uptr *ssize); void StopInitOrderChecking(); diff --git a/src/compiler-rt/lib/asan/asan_linux.cc b/src/compiler-rt/lib/asan/asan_linux.cc index 804aef7373..e26b400562 100644 --- a/src/compiler-rt/lib/asan/asan_linux.cc +++ b/src/compiler-rt/lib/asan/asan_linux.cc @@ -70,14 +70,6 @@ namespace __asan { void InitializePlatformInterceptors() {} -void DisableReexec() { - // No need to re-exec on Linux. -} - -void MaybeReexec() { - // No need to re-exec on Linux. -} - void *AsanDoesNotSupportStaticLinkage() { // This will fail to link with -static. return &_DYNAMIC; // defined in link.h diff --git a/src/compiler-rt/lib/asan/asan_mac.cc b/src/compiler-rt/lib/asan/asan_mac.cc index 8e23c71be5..f00d98f8e5 100644 --- a/src/compiler-rt/lib/asan/asan_mac.cc +++ b/src/compiler-rt/lib/asan/asan_mac.cc @@ -24,15 +24,6 @@ #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_mac.h" -#if !SANITIZER_IOS -#include // for _NSGetArgv and _NSGetEnviron -#else -extern "C" { - extern char ***_NSGetArgv(void); -} -#endif - -#include // for dladdr() #include #include #include @@ -52,182 +43,12 @@ void InitializePlatformInterceptors() {} bool PlatformHasDifferentMemcpyAndMemmove() { // On OS X 10.7 memcpy() and memmove() are both resolved // into memmove$VARIANT$sse42. - // See also http://code.google.com/p/address-sanitizer/issues/detail?id=34. + // See also https://github.com/google/sanitizers/issues/34. // TODO(glider): need to check dynamically that memcpy() and memmove() are // actually the same function. return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD; } -extern "C" -void __asan_init(); - -static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; -LowLevelAllocator allocator_for_env; - -// Change the value of the env var |name|, leaking the original value. -// If |name_value| is NULL, the variable is deleted from the environment, -// otherwise the corresponding "NAME=value" string is replaced with -// |name_value|. -void LeakyResetEnv(const char *name, const char *name_value) { - char **env = GetEnviron(); - uptr name_len = internal_strlen(name); - while (*env != 0) { - uptr len = internal_strlen(*env); - if (len > name_len) { - const char *p = *env; - if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') { - // Match. - if (name_value) { - // Replace the old value with the new one. - *env = const_cast(name_value); - } else { - // Shift the subsequent pointers back. - char **del = env; - do { - del[0] = del[1]; - } while (*del++); - } - } - } - env++; - } -} - -static bool reexec_disabled = false; - -void DisableReexec() { - reexec_disabled = true; -} - -extern "C" double dyldVersionNumber; -static const double kMinDyldVersionWithAutoInterposition = 360.0; - -bool DyldNeedsEnvVariable() { - // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if - // DYLD_INSERT_LIBRARIES is not set. However, checking OS version via - // GetMacosVersion() doesn't work for the simulator. Let's instead check - // `dyldVersionNumber`, which is exported by dyld, against a known version - // number from the first OS release where this appeared. - return dyldVersionNumber < kMinDyldVersionWithAutoInterposition; -} - -void MaybeReexec() { - if (reexec_disabled) return; - - // Make sure the dynamic ASan runtime library is preloaded so that the - // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec - // ourselves. - Dl_info info; - CHECK(dladdr((void*)((uptr)__asan_init), &info)); - char *dyld_insert_libraries = - const_cast(GetEnv(kDyldInsertLibraries)); - uptr old_env_len = dyld_insert_libraries ? - internal_strlen(dyld_insert_libraries) : 0; - uptr fname_len = internal_strlen(info.dli_fname); - const char *dylib_name = StripModuleName(info.dli_fname); - uptr dylib_name_len = internal_strlen(dylib_name); - - bool lib_is_in_env = - dyld_insert_libraries && REAL(strstr)(dyld_insert_libraries, dylib_name); - if (DyldNeedsEnvVariable() && !lib_is_in_env) { - // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime - // library. - char program_name[1024]; - uint32_t buf_size = sizeof(program_name); - _NSGetExecutablePath(program_name, &buf_size); - char *new_env = const_cast(info.dli_fname); - if (dyld_insert_libraries) { - // Append the runtime dylib name to the existing value of - // DYLD_INSERT_LIBRARIES. - new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2); - internal_strncpy(new_env, dyld_insert_libraries, old_env_len); - new_env[old_env_len] = ':'; - // Copy fname_len and add a trailing zero. - internal_strncpy(new_env + old_env_len + 1, info.dli_fname, - fname_len + 1); - // Ok to use setenv() since the wrappers don't depend on the value of - // asan_inited. - setenv(kDyldInsertLibraries, new_env, /*overwrite*/1); - } else { - // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name. - setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); - } - VReport(1, "exec()-ing the program with\n"); - VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env); - VReport(1, "to enable ASan wrappers.\n"); - execv(program_name, *_NSGetArgv()); - - // We get here only if execv() failed. - Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, " - "which is required for ASan to work. ASan tried to set the " - "environment variable and re-execute itself, but execv() failed, " - "possibly because of sandbox restrictions. Make sure to launch the " - "executable with:\n%s=%s\n", kDyldInsertLibraries, new_env); - CHECK("execv failed" && 0); - } - - if (!lib_is_in_env) - return; - - // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove - // the dylib from the environment variable, because interceptors are installed - // and we don't want our children to inherit the variable. - - uptr env_name_len = internal_strlen(kDyldInsertLibraries); - // Allocate memory to hold the previous env var name, its value, the '=' - // sign and the '\0' char. - char *new_env = (char*)allocator_for_env.Allocate( - old_env_len + 2 + env_name_len); - CHECK(new_env); - internal_memset(new_env, '\0', old_env_len + 2 + env_name_len); - internal_strncpy(new_env, kDyldInsertLibraries, env_name_len); - new_env[env_name_len] = '='; - char *new_env_pos = new_env + env_name_len + 1; - - // Iterate over colon-separated pieces of |dyld_insert_libraries|. - char *piece_start = dyld_insert_libraries; - char *piece_end = NULL; - char *old_env_end = dyld_insert_libraries + old_env_len; - do { - if (piece_start[0] == ':') piece_start++; - piece_end = REAL(strchr)(piece_start, ':'); - if (!piece_end) piece_end = dyld_insert_libraries + old_env_len; - if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break; - uptr piece_len = piece_end - piece_start; - - char *filename_start = - (char *)internal_memrchr(piece_start, '/', piece_len); - uptr filename_len = piece_len; - if (filename_start) { - filename_start += 1; - filename_len = piece_len - (filename_start - piece_start); - } else { - filename_start = piece_start; - } - - // If the current piece isn't the runtime library name, - // append it to new_env. - if ((dylib_name_len != filename_len) || - (internal_memcmp(filename_start, dylib_name, dylib_name_len) != 0)) { - if (new_env_pos != new_env + env_name_len + 1) { - new_env_pos[0] = ':'; - new_env_pos++; - } - internal_strncpy(new_env_pos, piece_start, piece_len); - new_env_pos += piece_len; - } - // Move on to the next piece. - piece_start = piece_end; - } while (piece_start < old_env_end); - - // Can't use setenv() here, because it requires the allocator to be - // initialized. - // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in - // a separate function called after InitializeAllocator(). - if (new_env_pos == new_env + env_name_len + 1) new_env = NULL; - LeakyResetEnv(kDyldInsertLibraries, new_env); -} - // No-op. Mac does not support static linkage anyway. void *AsanDoesNotSupportStaticLinkage() { return 0; diff --git a/src/compiler-rt/lib/asan/asan_malloc_linux.cc b/src/compiler-rt/lib/asan/asan_malloc_linux.cc index 46a6a9db4a..d5089f9f7b 100644 --- a/src/compiler-rt/lib/asan/asan_malloc_linux.cc +++ b/src/compiler-rt/lib/asan/asan_malloc_linux.cc @@ -26,13 +26,25 @@ // ---------------------- Replacement functions ---------------- {{{1 using namespace __asan; // NOLINT +static const uptr kCallocPoolSize = 1024; +static uptr calloc_memory_for_dlsym[kCallocPoolSize]; + +static bool IsInCallocPool(const void *ptr) { + sptr off = (sptr)ptr - (sptr)calloc_memory_for_dlsym; + return 0 <= off && off < (sptr)kCallocPoolSize; +} + INTERCEPTOR(void, free, void *ptr) { GET_STACK_TRACE_FREE; + if (UNLIKELY(IsInCallocPool(ptr))) + return; asan_free(ptr, &stack, FROM_MALLOC); } INTERCEPTOR(void, cfree, void *ptr) { GET_STACK_TRACE_FREE; + if (UNLIKELY(IsInCallocPool(ptr))) + return; asan_free(ptr, &stack, FROM_MALLOC); } @@ -44,8 +56,6 @@ INTERCEPTOR(void*, malloc, uptr size) { INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { if (UNLIKELY(!asan_inited)) { // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. - const uptr kCallocPoolSize = 1024; - static uptr calloc_memory_for_dlsym[kCallocPoolSize]; static uptr allocated; uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; void *mem = (void*)&calloc_memory_for_dlsym[allocated]; @@ -59,6 +69,13 @@ INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { INTERCEPTOR(void*, realloc, void *ptr, uptr size) { GET_STACK_TRACE_MALLOC; + if (UNLIKELY(IsInCallocPool(ptr))) { + uptr offset = (uptr)ptr - (uptr)calloc_memory_for_dlsym; + uptr copy_size = Min(size, kCallocPoolSize - offset); + void *new_ptr = asan_malloc(size, &stack); + internal_memcpy(new_ptr, ptr, copy_size); + return new_ptr; + } return asan_realloc(ptr, size, &stack); } diff --git a/src/compiler-rt/lib/asan/asan_malloc_mac.cc b/src/compiler-rt/lib/asan/asan_malloc_mac.cc index 312c1c34fc..744728d40d 100644 --- a/src/compiler-rt/lib/asan/asan_malloc_mac.cc +++ b/src/compiler-rt/lib/asan/asan_malloc_mac.cc @@ -54,10 +54,6 @@ using namespace __asan; #define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \ GET_STACK_TRACE_FREE; \ ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); -#define COMMON_MALLOC_IGNORE_INVALID_FREE flags()->mac_ignore_invalid_free -#define COMMON_MALLOC_REPORT_FREE_UNALLOCATED(ptr, zone_ptr, zone_name) \ - GET_STACK_TRACE_FREE; \ - WarnMacFreeUnallocated((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); #define COMMON_MALLOC_NAMESPACE __asan #include "sanitizer_common/sanitizer_malloc_mac.inc" diff --git a/src/compiler-rt/lib/asan/asan_mapping.h b/src/compiler-rt/lib/asan/asan_mapping.h index f76ca53c36..8fe347c8ba 100644 --- a/src/compiler-rt/lib/asan/asan_mapping.h +++ b/src/compiler-rt/lib/asan/asan_mapping.h @@ -17,7 +17,7 @@ #include "asan_internal.h" // The full explanation of the memory mapping could be found here: -// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm +// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm // // Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000: // || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || @@ -118,11 +118,7 @@ static const u64 kIosShadowOffset32 = 1ULL << 30; // 0x40000000 static const u64 kIosShadowOffset64 = 0x130000000; static const u64 kIosSimShadowOffset32 = 1ULL << 30; static const u64 kIosSimShadowOffset64 = kDefaultShadowOffset64; -#if SANITIZER_AARCH64_VMA == 39 static const u64 kAArch64_ShadowOffset64 = 1ULL << 36; -#elif SANITIZER_AARCH64_VMA == 42 -static const u64 kAArch64_ShadowOffset64 = 1ULL << 39; -#endif static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000; static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37; static const u64 kPPC64_ShadowOffset64 = 1ULL << 41; diff --git a/src/compiler-rt/lib/asan/asan_new_delete.cc b/src/compiler-rt/lib/asan/asan_new_delete.cc index cd7f1632e4..b5ba13ef40 100644 --- a/src/compiler-rt/lib/asan/asan_new_delete.cc +++ b/src/compiler-rt/lib/asan/asan_new_delete.cc @@ -30,7 +30,7 @@ using namespace __asan; // NOLINT // This code has issues on OSX. -// See https://code.google.com/p/address-sanitizer/issues/detail?id=131. +// See https://github.com/google/sanitizers/issues/131. // Fake std::nothrow_t to avoid including . namespace std { diff --git a/src/compiler-rt/lib/asan/asan_poisoning.cc b/src/compiler-rt/lib/asan/asan_poisoning.cc index 0082e845fc..f77ab8780b 100644 --- a/src/compiler-rt/lib/asan/asan_poisoning.cc +++ b/src/compiler-rt/lib/asan/asan_poisoning.cc @@ -102,7 +102,7 @@ using namespace __asan; // NOLINT // that user program (un)poisons the memory it owns. It poisons memory // conservatively, and unpoisons progressively to make sure asan shadow // mapping invariant is preserved (see detailed mapping description here: -// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm). +// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm). // // * if user asks to poison region [left, right), the program poisons // at least [left, AlignDown(right)). @@ -354,7 +354,7 @@ void __sanitizer_annotate_contiguous_container(const void *beg_p, // Make a quick sanity check that we are indeed in this state. // // FIXME: Two of these three checks are disabled until we fix - // https://code.google.com/p/address-sanitizer/issues/detail?id=258. + // https://github.com/google/sanitizers/issues/258. // if (d1 != d2) // CHECK_EQ(*(u8*)MemToShadow(d1), old_mid - d1); if (a + granularity <= d1) diff --git a/src/compiler-rt/lib/asan/asan_posix.cc b/src/compiler-rt/lib/asan/asan_posix.cc index cce56984ec..9e01bcd091 100644 --- a/src/compiler-rt/lib/asan/asan_posix.cc +++ b/src/compiler-rt/lib/asan/asan_posix.cc @@ -77,6 +77,8 @@ void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { ReportStackOverflow(sig); else if (signo == SIGFPE) ReportDeadlySignal("FPE", sig); + else if (signo == SIGILL) + ReportDeadlySignal("ILL", sig); else ReportDeadlySignal("SEGV", sig); } diff --git a/src/compiler-rt/lib/asan/asan_report.cc b/src/compiler-rt/lib/asan/asan_report.cc index 957ac14eaf..bb7e36e846 100644 --- a/src/compiler-rt/lib/asan/asan_report.cc +++ b/src/compiler-rt/lib/asan/asan_report.cc @@ -30,7 +30,9 @@ namespace __asan { static void (*error_report_callback)(const char*); static char *error_message_buffer = nullptr; static uptr error_message_buffer_pos = 0; -static uptr error_message_buffer_size = 0; +static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED); +static const unsigned kAsanBuggyPcPoolSize = 25; +static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize]; struct ReportData { uptr pc; @@ -46,16 +48,20 @@ static bool report_happened = false; static ReportData report_data = {}; void AppendToErrorMessageBuffer(const char *buffer) { - if (error_message_buffer) { - uptr length = internal_strlen(buffer); - CHECK_GE(error_message_buffer_size, error_message_buffer_pos); - uptr remaining = error_message_buffer_size - error_message_buffer_pos; - internal_strncpy(error_message_buffer + error_message_buffer_pos, - buffer, remaining); - error_message_buffer[error_message_buffer_size - 1] = '\0'; - // FIXME: reallocate the buffer instead of truncating the message. - error_message_buffer_pos += Min(remaining, length); + BlockingMutexLock l(&error_message_buf_mutex); + if (!error_message_buffer) { + error_message_buffer = + (char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__); + error_message_buffer_pos = 0; } + uptr length = internal_strlen(buffer); + RAW_CHECK(kErrorMessageBufferSize >= error_message_buffer_pos); + uptr remaining = kErrorMessageBufferSize - error_message_buffer_pos; + internal_strncpy(error_message_buffer + error_message_buffer_pos, + buffer, remaining); + error_message_buffer[kErrorMessageBufferSize - 1] = '\0'; + // FIXME: reallocate the buffer instead of truncating the message. + error_message_buffer_pos += Min(remaining, length); } // ---------------------- Decorator ------------------------------ {{{1 @@ -622,26 +628,90 @@ void DescribeThread(AsanThreadContext *context) { // immediately after printing error report. class ScopedInErrorReport { public: - explicit ScopedInErrorReport(ReportData *report = nullptr) { - static atomic_uint32_t num_calls; - static u32 reporting_thread_tid; - if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { + explicit ScopedInErrorReport(ReportData *report = nullptr, + bool fatal = false) { + halt_on_error_ = fatal || flags()->halt_on_error; + + if (lock_.TryLock()) { + StartReporting(report); + return; + } + + // ASan found two bugs in different threads simultaneously. + + u32 current_tid = GetCurrentTidOrInvalid(); + if (reporting_thread_tid_ == current_tid || + reporting_thread_tid_ == kInvalidTid) { + // This is either asynch signal or nested error during error reporting. + // Fail simple to avoid deadlocks in Report(). + + // Can't use Report() here because of potential deadlocks + // in nested signal handlers. + const char msg[] = "AddressSanitizer: nested bug in the same thread, " + "aborting.\n"; + WriteToFile(kStderrFd, msg, sizeof(msg)); + + internal__exit(common_flags()->exitcode); + } + + if (halt_on_error_) { // Do not print more than one report, otherwise they will mix up. // Error reporting functions shouldn't return at this situation, as - // they are defined as no-return. + // they are effectively no-returns. + Report("AddressSanitizer: while reporting a bug found another one. " - "Ignoring.\n"); - u32 current_tid = GetCurrentTidOrInvalid(); - if (current_tid != reporting_thread_tid) { - // ASan found two bugs in different threads simultaneously. Sleep - // long enough to make sure that the thread which started to print - // an error report will finish doing it. - SleepForSeconds(Max(100, flags()->sleep_before_dying + 1)); - } + "Ignoring.\n"); + + // Sleep long enough to make sure that the thread which started + // to print an error report will finish doing it. + SleepForSeconds(Max(100, flags()->sleep_before_dying + 1)); + // If we're still not dead for some reason, use raw _exit() instead of // Die() to bypass any additional checks. internal__exit(common_flags()->exitcode); + } else { + // The other thread will eventually finish reporting + // so it's safe to wait + lock_.Lock(); + } + + StartReporting(report); + } + + ~ScopedInErrorReport() { + // Make sure the current thread is announced. + DescribeThread(GetCurrentThread()); + // We may want to grab this lock again when printing stats. + asanThreadRegistry().Unlock(); + // Print memory stats. + if (flags()->print_stats) + __asan_print_accumulated_stats(); + + // Copy the message buffer so that we could start logging without holding a + // lock that gets aquired during printing. + InternalScopedBuffer buffer_copy(kErrorMessageBufferSize); + { + BlockingMutexLock l(&error_message_buf_mutex); + internal_memcpy(buffer_copy.data(), + error_message_buffer, kErrorMessageBufferSize); + } + + LogFullErrorReport(buffer_copy.data()); + + if (error_report_callback) { + error_report_callback(buffer_copy.data()); + } + CommonSanitizerReportMutex.Unlock(); + reporting_thread_tid_ = kInvalidTid; + lock_.Unlock(); + if (halt_on_error_) { + Report("ABORTING\n"); + Die(); } + } + + private: + void StartReporting(ReportData *report) { if (report) report_data = *report; report_happened = true; ASAN_ON_ERROR(); @@ -651,27 +721,19 @@ class ScopedInErrorReport { // recursive reports. asanThreadRegistry().Lock(); CommonSanitizerReportMutex.Lock(); - reporting_thread_tid = GetCurrentTidOrInvalid(); + reporting_thread_tid_ = GetCurrentTidOrInvalid(); Printf("====================================================" "=============\n"); } - // Destructor is NORETURN, as functions that report errors are. - NORETURN ~ScopedInErrorReport() { - // Make sure the current thread is announced. - DescribeThread(GetCurrentThread()); - // We may want to grab this lock again when printing stats. - asanThreadRegistry().Unlock(); - // Print memory stats. - if (flags()->print_stats) - __asan_print_accumulated_stats(); - if (error_report_callback) { - error_report_callback(error_message_buffer); - } - Report("ABORTING\n"); - Die(); - } + + static StaticSpinMutex lock_; + static u32 reporting_thread_tid_; + bool halt_on_error_; }; +StaticSpinMutex ScopedInErrorReport::lock_; +u32 ScopedInErrorReport::reporting_thread_tid_; + void ReportStackOverflow(const SignalContext &sig) { ScopedInErrorReport in_report; Decorator d; @@ -688,7 +750,7 @@ void ReportStackOverflow(const SignalContext &sig) { } void ReportDeadlySignal(const char *description, const SignalContext &sig) { - ScopedInErrorReport in_report; + ScopedInErrorReport in_report(/*report*/nullptr, /*fatal*/true); Decorator d; Printf("%s", d.Warning()); Report( @@ -745,7 +807,7 @@ void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, stack.Print(); DescribeHeapAddress(addr, 1); ReportErrorSummary("new-delete-type-mismatch", &stack); - Report("HINT: if you don't care about these warnings you may set " + Report("HINT: if you don't care about these errors you may set " "ASAN_OPTIONS=new_delete_type_mismatch=0\n"); } @@ -785,7 +847,7 @@ void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack, stack.Print(); DescribeHeapAddress(addr, 1); ReportErrorSummary("alloc-dealloc-mismatch", &stack); - Report("HINT: if you don't care about these warnings you may set " + Report("HINT: if you don't care about these errors you may set " "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n"); } @@ -887,7 +949,7 @@ void ReportODRViolation(const __asan_global *g1, u32 stack_id1, Printf(" [2]:\n"); StackDepotGet(stack_id2).Print(); } - Report("HINT: if you don't care about these warnings you may set " + Report("HINT: if you don't care about these errors you may set " "ASAN_OPTIONS=detect_odr_violation=0\n"); InternalScopedString error_msg(256); error_msg.append("odr-violation: global '%s' at %s", @@ -926,17 +988,6 @@ static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) { } // ----------------------- Mac-specific reports ----------------- {{{1 -void WarnMacFreeUnallocated(uptr addr, uptr zone_ptr, const char *zone_name, - BufferedStackTrace *stack) { - // Just print a warning here. - Printf("free_common(%p) -- attempting to free unallocated memory.\n" - "AddressSanitizer is ignoring this error on Mac OS now.\n", - addr); - PrintZoneForPointer(addr, zone_ptr, zone_name); - stack->Print(); - DescribeHeapAddress(addr, 1); -} - void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name, BufferedStackTrace *stack) { ScopedInErrorReport in_report; @@ -948,24 +999,23 @@ void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name, DescribeHeapAddress(addr, 1); } -void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name, - BufferedStackTrace *stack) { - ScopedInErrorReport in_report; - Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n" - "This is an unrecoverable problem, exiting now.\n", - addr); - PrintZoneForPointer(addr, zone_ptr, zone_name); - stack->Print(); - DescribeHeapAddress(addr, 1); +// -------------- SuppressErrorReport -------------- {{{1 +// Avoid error reports duplicating for ASan recover mode. +static bool SuppressErrorReport(uptr pc) { + if (!common_flags()->suppress_equal_pcs) return false; + for (unsigned i = 0; i < kAsanBuggyPcPoolSize; i++) { + uptr cmp = atomic_load_relaxed(&AsanBuggyPcPool[i]); + if (cmp == 0 && atomic_compare_exchange_strong(&AsanBuggyPcPool[i], &cmp, + pc, memory_order_relaxed)) + return false; + if (cmp == pc) return true; + } + Die(); } -} // namespace __asan - -// --------------------------- Interface --------------------- {{{1 -using namespace __asan; // NOLINT - -void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, - uptr access_size, u32 exp) { +void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write, + uptr access_size, u32 exp, bool fatal) { + if (!fatal && SuppressErrorReport(pc)) return; ENABLE_FRAME_POINTER; // Optimization experiments. @@ -1034,7 +1084,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, ReportData report = { pc, sp, bp, addr, (bool)is_write, access_size, bug_descr }; - ScopedInErrorReport in_report(&report); + ScopedInErrorReport in_report(&report, fatal); Decorator d; Printf("%s", d.Warning()); @@ -1060,14 +1110,21 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, PrintShadowMemoryForAddress(addr); } +} // namespace __asan + +// --------------------------- Interface --------------------- {{{1 +using namespace __asan; // NOLINT + +void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, + uptr access_size, u32 exp) { + ENABLE_FRAME_POINTER; + bool fatal = flags()->halt_on_error; + ReportGenericError(pc, bp, sp, addr, is_write, access_size, exp, fatal); +} + void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) { + BlockingMutexLock l(&error_message_buf_mutex); error_report_callback = callback; - if (callback) { - error_message_buffer_size = 1 << 16; - error_message_buffer = - (char*)MmapOrDie(error_message_buffer_size, __func__); - error_message_buffer_pos = 0; - } } void __asan_describe_address(uptr addr) { diff --git a/src/compiler-rt/lib/asan/asan_report.h b/src/compiler-rt/lib/asan/asan_report.h index e971eb1d6e..559b8adfd5 100644 --- a/src/compiler-rt/lib/asan/asan_report.h +++ b/src/compiler-rt/lib/asan/asan_report.h @@ -49,45 +49,39 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size); void DescribeThread(AsanThreadContext *context); // Different kinds of error reports. -void NORETURN ReportStackOverflow(const SignalContext &sig); -void NORETURN ReportDeadlySignal(const char* description, - const SignalContext &sig); -void NORETURN ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, - BufferedStackTrace *free_stack); -void NORETURN ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack); -void NORETURN ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack); -void NORETURN ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack, - AllocType alloc_type, - AllocType dealloc_type); -void NORETURN - ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack); -void NORETURN - ReportSanitizerGetAllocatedSizeNotOwned(uptr addr, - BufferedStackTrace *stack); -void NORETURN - ReportStringFunctionMemoryRangesOverlap(const char *function, - const char *offset1, uptr length1, - const char *offset2, uptr length2, - BufferedStackTrace *stack); -void NORETURN ReportStringFunctionSizeOverflow(uptr offset, uptr size, - BufferedStackTrace *stack); -void NORETURN - ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, - uptr old_mid, uptr new_mid, - BufferedStackTrace *stack); +void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write, + uptr access_size, u32 exp, bool fatal); +void ReportStackOverflow(const SignalContext &sig); +void ReportDeadlySignal(const char *description, const SignalContext &sig); +void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, + BufferedStackTrace *free_stack); +void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack); +void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack); +void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack, + AllocType alloc_type, + AllocType dealloc_type); +void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack); +void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr, + BufferedStackTrace *stack); +void ReportStringFunctionMemoryRangesOverlap(const char *function, + const char *offset1, uptr length1, + const char *offset2, uptr length2, + BufferedStackTrace *stack); +void ReportStringFunctionSizeOverflow(uptr offset, uptr size, + BufferedStackTrace *stack); +void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, + uptr old_mid, uptr new_mid, + BufferedStackTrace *stack); -void NORETURN -ReportODRViolation(const __asan_global *g1, u32 stack_id1, - const __asan_global *g2, u32 stack_id2); +void ReportODRViolation(const __asan_global *g1, u32 stack_id1, + const __asan_global *g2, u32 stack_id2); // Mac-specific errors and warnings. -void WarnMacFreeUnallocated(uptr addr, uptr zone_ptr, const char *zone_name, - BufferedStackTrace *stack); -void NORETURN ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, - const char *zone_name, - BufferedStackTrace *stack); -void NORETURN ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr, - const char *zone_name, - BufferedStackTrace *stack); +void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, + const char *zone_name, + BufferedStackTrace *stack); +void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr, + const char *zone_name, + BufferedStackTrace *stack); } // namespace __asan diff --git a/src/compiler-rt/lib/asan/asan_rtl.cc b/src/compiler-rt/lib/asan/asan_rtl.cc index c744ac2519..7b8b5dd9be 100644 --- a/src/compiler-rt/lib/asan/asan_rtl.cc +++ b/src/compiler-rt/lib/asan/asan_rtl.cc @@ -113,13 +113,18 @@ static void OnLowLevelAllocate(uptr ptr, uptr size) { 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); \ + ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ } \ 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, exp); \ -} + ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ +} \ +extern "C" NOINLINE INTERFACE_ATTRIBUTE \ +void __asan_report_ ## type ## size ## _noabort(uptr addr) { \ + GET_CALLER_PC_BP_SP; \ + ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ +} \ ASAN_REPORT_ERROR(load, false, 1) ASAN_REPORT_ERROR(load, false, 2) @@ -132,22 +137,27 @@ ASAN_REPORT_ERROR(store, true, 4) ASAN_REPORT_ERROR(store, true, 8) 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) { \ - GET_CALLER_PC_BP_SP; \ - __asan_report_error(pc, bp, sp, addr, is_write, size, 0); \ -} \ -extern "C" NOINLINE INTERFACE_ATTRIBUTE \ +#define ASAN_REPORT_ERROR_N(type, is_write) \ +extern "C" NOINLINE INTERFACE_ATTRIBUTE \ +void __asan_report_ ## type ## _n(uptr addr, uptr size) { \ + GET_CALLER_PC_BP_SP; \ + ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ +} \ +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); \ -} + ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ +} \ +extern "C" NOINLINE INTERFACE_ATTRIBUTE \ +void __asan_report_ ## type ## _n_noabort(uptr addr, uptr size) { \ + GET_CALLER_PC_BP_SP; \ + ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ +} \ ASAN_REPORT_ERROR_N(load, false) ASAN_REPORT_ERROR_N(store, true) -#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg) \ +#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg, fatal) \ uptr sp = MEM_TO_SHADOW(addr); \ uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast(sp) \ : *reinterpret_cast(sp); \ @@ -159,7 +169,8 @@ 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, exp_arg); \ + ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, \ + fatal); \ } \ } \ } @@ -167,12 +178,16 @@ 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) { \ - ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0) \ + ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, true) \ } \ 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_BODY(type, is_write, size, exp, true) \ + } \ + extern "C" NOINLINE INTERFACE_ATTRIBUTE \ + void __asan_##type##size ## _noabort(uptr addr) { \ + ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, false) \ + } \ ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1) ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2) @@ -190,7 +205,7 @@ 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); + ReportGenericError(pc, bp, sp, addr, false, size, 0, true); } } @@ -199,7 +214,16 @@ 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); + ReportGenericError(pc, bp, sp, addr, false, size, exp, true); + } +} + +extern "C" +NOINLINE INTERFACE_ATTRIBUTE +void __asan_loadN_noabort(uptr addr, uptr size) { + if (__asan_region_is_poisoned(addr, size)) { + GET_CALLER_PC_BP_SP; + ReportGenericError(pc, bp, sp, addr, false, size, 0, false); } } @@ -208,7 +232,7 @@ 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, true, size, 0); + ReportGenericError(pc, bp, sp, addr, true, size, 0, true); } } @@ -217,7 +241,16 @@ 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, exp); + ReportGenericError(pc, bp, sp, addr, true, size, exp, true); + } +} + +extern "C" +NOINLINE INTERFACE_ATTRIBUTE +void __asan_storeN_noabort(uptr addr, uptr size) { + if (__asan_region_is_poisoned(addr, size)) { + GET_CALLER_PC_BP_SP; + ReportGenericError(pc, bp, sp, addr, true, size, 0, false); } } @@ -293,6 +326,8 @@ static void InitializeHighMemEnd() { } static void ProtectGap(uptr addr, uptr size) { + if (!flags()->protect_shadow_gap) + return; void *res = MmapNoAccess(addr, size, "shadow gap"); if (addr == (uptr)res) return; @@ -378,8 +413,6 @@ static void AsanInitInternal() { // initialization steps look at flags(). InitializeFlags(); - CheckVMASize(); - AsanCheckIncompatibleRT(); AsanCheckDynamicRTPrereqs(); @@ -572,7 +605,7 @@ void NOINLINE __asan_handle_no_return() { "stack top: %p; bottom %p; size: %p (%zd)\n" "False positive error reports may follow\n" "For details see " - "http://code.google.com/p/address-sanitizer/issues/detail?id=189\n", + "https://github.com/google/sanitizers/issues/189\n", top, bottom, top - bottom, top - bottom); return; } diff --git a/src/compiler-rt/lib/asan/asan_win.cc b/src/compiler-rt/lib/asan/asan_win.cc index 28ec076807..92bd893d10 100644 --- a/src/compiler-rt/lib/asan/asan_win.cc +++ b/src/compiler-rt/lib/asan/asan_win.cc @@ -175,14 +175,6 @@ void PlatformTSDDtor(void *tsd) { // }}} // ---------------------- Various stuff ---------------- {{{ -void DisableReexec() { - // No need to re-exec on Windows. -} - -void MaybeReexec() { - // No need to re-exec on Windows. -} - void *AsanDoesNotSupportStaticLinkage() { #if defined(_DEBUG) #error Please build the runtime with a non-debug CRT: /MD or /MT diff --git a/src/compiler-rt/lib/asan/asan_win_dll_thunk.cc b/src/compiler-rt/lib/asan/asan_win_dll_thunk.cc index b8d0798960..672cabf43e 100644 --- a/src/compiler-rt/lib/asan/asan_win_dll_thunk.cc +++ b/src/compiler-rt/lib/asan/asan_win_dll_thunk.cc @@ -12,8 +12,7 @@ // This file defines a family of thunks that should be statically linked into // the DLLs that have ASan instrumentation in order to delegate the calls to the // shared runtime that lives in the main binary. -// See https://code.google.com/p/address-sanitizer/issues/detail?id=209 for the -// details. +// See https://github.com/google/sanitizers/issues/209 for the details. //===----------------------------------------------------------------------===// // Only compile this code when buidling asan_dll_thunk.lib @@ -257,6 +256,9 @@ INTERFACE_FUNCTION(__asan_memcpy); INTERFACE_FUNCTION(__asan_memset); INTERFACE_FUNCTION(__asan_memmove); +INTERFACE_FUNCTION(__asan_alloca_poison); +INTERFACE_FUNCTION(__asan_allocas_unpoison); + INTERFACE_FUNCTION(__asan_register_globals) INTERFACE_FUNCTION(__asan_unregister_globals) @@ -300,6 +302,7 @@ INTERFACE_FUNCTION(__asan_stack_free_10) // FIXME: we might want to have a sanitizer_win_dll_thunk? INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container) +INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address) INTERFACE_FUNCTION(__sanitizer_cov) INTERFACE_FUNCTION(__sanitizer_cov_dump) INTERFACE_FUNCTION(__sanitizer_cov_indir_call16) @@ -312,11 +315,13 @@ INTERFACE_FUNCTION(__sanitizer_cov_trace_switch) INTERFACE_FUNCTION(__sanitizer_cov_with_check) INTERFACE_FUNCTION(__sanitizer_get_allocated_size) INTERFACE_FUNCTION(__sanitizer_get_coverage_guards) +INTERFACE_FUNCTION(__sanitizer_get_coverage_pc_buffer) INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes) INTERFACE_FUNCTION(__sanitizer_get_estimated_allocated_size) INTERFACE_FUNCTION(__sanitizer_get_free_bytes) INTERFACE_FUNCTION(__sanitizer_get_heap_size) INTERFACE_FUNCTION(__sanitizer_get_ownership) +INTERFACE_FUNCTION(__sanitizer_get_total_unique_caller_callee_pairs) INTERFACE_FUNCTION(__sanitizer_get_total_unique_coverage) INTERFACE_FUNCTION(__sanitizer_get_unmapped_bytes) INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file) diff --git a/src/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc b/src/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc index d5a14088da..73e5207bb3 100644 --- a/src/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc +++ b/src/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc @@ -59,6 +59,7 @@ int __asan_option_detect_stack_use_after_return = // 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" int __cdecl atexit(void (__cdecl *f)(void)); extern "C" void __cdecl _initterm(void *a, void *b); namespace { diff --git a/src/compiler-rt/lib/asan/scripts/asan_device_setup b/src/compiler-rt/lib/asan/scripts/asan_device_setup index 338b8d501b..6cb7b94c21 100755 --- a/src/compiler-rt/lib/asan/scripts/asan_device_setup +++ b/src/compiler-rt/lib/asan/scripts/asan_device_setup @@ -222,8 +222,13 @@ elif [[ -f "$HERE/$ASAN_RT" ]]; then ASAN_RT_PATH="$HERE" elif [[ $(basename "$HERE") == "bin" ]]; then # We could be in the toolchain's base directory. - # Consider ../lib, ../lib/asan, ../lib/linux and ../lib/clang/$VERSION/lib/linux. - P=$(ls "$HERE"/../lib/"$ASAN_RT" "$HERE"/../lib/asan/"$ASAN_RT" "$HERE"/../lib/linux/"$ASAN_RT" "$HERE"/../lib/clang/*/lib/linux/"$ASAN_RT" 2>/dev/null | sort | tail -1) + # Consider ../lib, ../lib/asan, ../lib/linux, + # ../lib/clang/$VERSION/lib/linux, and ../lib64/clang/$VERSION/lib/linux. + P=$(ls "$HERE"/../lib/"$ASAN_RT" \ + "$HERE"/../lib/asan/"$ASAN_RT" \ + "$HERE"/../lib/linux/"$ASAN_RT" \ + "$HERE"/../lib/clang/*/lib/linux/"$ASAN_RT" \ + "$HERE"/../lib64/clang/*/lib/linux/"$ASAN_RT" 2>/dev/null | sort | tail -1) if [[ -n "$P" ]]; then ASAN_RT_PATH="$(dirname "$P")" fi diff --git a/src/compiler-rt/lib/asan/scripts/asan_symbolize.py b/src/compiler-rt/lib/asan/scripts/asan_symbolize.py index e6d43cd3f4..8e6fb61f7b 100755 --- a/src/compiler-rt/lib/asan/scripts/asan_symbolize.py +++ b/src/compiler-rt/lib/asan/scripts/asan_symbolize.py @@ -271,7 +271,7 @@ def BreakpadSymbolizerFactory(binary): def SystemSymbolizerFactory(system, addr, binary): if system == 'Darwin': return DarwinSymbolizer(addr, binary) - elif system == 'Linux': + elif system == 'Linux' or system == 'FreeBSD': return Addr2LineSymbolizer(binary) diff --git a/src/compiler-rt/lib/asan/tests/asan_mac_test.cc b/src/compiler-rt/lib/asan/tests/asan_mac_test.cc index cabdfd711e..dfa6d7596d 100644 --- a/src/compiler-rt/lib/asan/tests/asan_mac_test.cc +++ b/src/compiler-rt/lib/asan/tests/asan_mac_test.cc @@ -216,12 +216,12 @@ TEST(AddressSanitizerMac, NSObjectOOB) { // Make sure that correct pointer is passed to free() when deallocating a // NSURL object. -// See http://code.google.com/p/address-sanitizer/issues/detail?id=70. +// See https://github.com/google/sanitizers/issues/70. TEST(AddressSanitizerMac, NSURLDeallocation) { TestNSURLDeallocation(); } -// See http://code.google.com/p/address-sanitizer/issues/detail?id=109. +// See https://github.com/google/sanitizers/issues/109. TEST(AddressSanitizerMac, Mstats) { malloc_statistics_t stats1, stats2; malloc_zone_statistics(/*all zones*/NULL, &stats1); diff --git a/src/compiler-rt/lib/asan/tests/asan_noinst_test.cc b/src/compiler-rt/lib/asan/tests/asan_noinst_test.cc index 6a428fbbc2..5f5354f92c 100644 --- a/src/compiler-rt/lib/asan/tests/asan_noinst_test.cc +++ b/src/compiler-rt/lib/asan/tests/asan_noinst_test.cc @@ -34,7 +34,7 @@ // Make sure __asan_init is called before any test case is run. struct AsanInitCaller { AsanInitCaller() { - __asan::DisableReexec(); + DisableReexec(); __asan_init(); } }; diff --git a/src/compiler-rt/lib/asan/tests/asan_test.cc b/src/compiler-rt/lib/asan/tests/asan_test.cc index ed796d6259..71fb27a0ca 100644 --- a/src/compiler-rt/lib/asan/tests/asan_test.cc +++ b/src/compiler-rt/lib/asan/tests/asan_test.cc @@ -610,7 +610,7 @@ NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) { } // Does not work on Power and ARM: -// https://code.google.com/p/address-sanitizer/issues/detail?id=185 +// https://github.com/google/sanitizers/issues/185 TEST(AddressSanitizer, BuiltinLongJmpTest) { static jmp_buf buf; if (!__builtin_setjmp((void**)buf)) { @@ -1156,9 +1156,9 @@ TEST(AddressSanitizer, AttributeNoSanitizeAddressTest) { // The new/delete/etc mismatch checks don't work on Android, // as calls to new/delete go through malloc/free. // OS X support is tracked here: -// https://code.google.com/p/address-sanitizer/issues/detail?id=131 +// https://github.com/google/sanitizers/issues/131 // Windows support is tracked here: -// https://code.google.com/p/address-sanitizer/issues/detail?id=309 +// https://github.com/google/sanitizers/issues/309 #if !defined(__ANDROID__) && \ !defined(__APPLE__) && \ !defined(_WIN32) @@ -1255,7 +1255,7 @@ TEST(AddressSanitizer, DISABLED_DemoTooMuchMemoryTest) { } } -// http://code.google.com/p/address-sanitizer/issues/detail?id=66 +// https://github.com/google/sanitizers/issues/66 TEST(AddressSanitizer, BufferOverflowAfterManyFrees) { for (int i = 0; i < 1000000; i++) { delete [] (Ident(new char [8644])); diff --git a/src/compiler-rt/lib/asan/tests/asan_test_main.cc b/src/compiler-rt/lib/asan/tests/asan_test_main.cc index 5958cb8a06..cdaf801d91 100644 --- a/src/compiler-rt/lib/asan/tests/asan_test_main.cc +++ b/src/compiler-rt/lib/asan/tests/asan_test_main.cc @@ -19,7 +19,8 @@ extern "C" const char* __asan_default_options() { #if SANITIZER_MAC // On Darwin, we default to `abort_on_error=1`, which would make tests run // much slower. Let's override this and run lit tests with 'abort_on_error=0'. - return "symbolize=false:abort_on_error=0"; + // Also, make sure we do not overwhelm the syslog while testing. + return "symbolize=false:abort_on_error=0:log_to_syslog=0"; #else return "symbolize=false"; #endif diff --git a/src/compiler-rt/lib/builtins/CMakeLists.txt b/src/compiler-rt/lib/builtins/CMakeLists.txt index 9f9f4304d7..f87a19c806 100644 --- a/src/compiler-rt/lib/builtins/CMakeLists.txt +++ b/src/compiler-rt/lib/builtins/CMakeLists.txt @@ -2,6 +2,9 @@ # generic implementations of the core runtime library along with optimized # architecture-specific code in various subdirectories. +# TODO: Need to add a mechanism for logging errors when builtin source files are +# added to a sub-directory and not this CMakeLists file. + set(GENERIC_SOURCES absvdi2.c absvsi2.c @@ -150,7 +153,7 @@ if(APPLE) atomic_thread_fence.c) endif() -if(NOT WIN32) +if(NOT WIN32 OR MINGW) set(GENERIC_SOURCES ${GENERIC_SOURCES} emutls.c) @@ -164,6 +167,8 @@ endif () if (NOT MSVC) set(x86_64_SOURCES + x86_64/chkstk.S + x86_64/chkstk2.S x86_64/floatdidf.c x86_64/floatdisf.c x86_64/floatdixf.c @@ -183,6 +188,8 @@ if (NOT MSVC) set(i386_SOURCES i386/ashldi3.S i386/ashrdi3.S + i386/chkstk.S + i386/chkstk2.S i386/divdi3.S i386/floatdidf.S i386/floatdisf.S @@ -219,7 +226,8 @@ else () # MSVC set(i686_SOURCES ${i386_SOURCES}) endif () # if (NOT MSVC) -set(arm_SOURCES +# These are sources that should be appropriate for any ARM platform. +set(arm_GENERIC_SOURCES arm/aeabi_cdcmp.S arm/aeabi_cdcmpeq_check_nan.c arm/aeabi_cfcmp.S @@ -239,36 +247,16 @@ set(arm_SOURCES arm/aeabi_uldivmod.S arm/bswapdi2.S arm/bswapsi2.S + arm/clzdi2.S + arm/clzsi2.S arm/comparesf2.S arm/divmodsi4.S arm/divsi3.S arm/modsi3.S - arm/negdf2vfp.S - arm/negsf2vfp.S arm/switch16.S arm/switch32.S arm/switch8.S arm/switchu8.S - arm/sync_fetch_and_add_4.S - arm/sync_fetch_and_add_8.S - arm/sync_fetch_and_and_4.S - arm/sync_fetch_and_and_8.S - arm/sync_fetch_and_max_4.S - arm/sync_fetch_and_max_8.S - arm/sync_fetch_and_min_4.S - arm/sync_fetch_and_min_8.S - arm/sync_fetch_and_nand_4.S - arm/sync_fetch_and_nand_8.S - arm/sync_fetch_and_or_4.S - arm/sync_fetch_and_or_8.S - arm/sync_fetch_and_sub_4.S - arm/sync_fetch_and_sub_8.S - arm/sync_fetch_and_umax_4.S - arm/sync_fetch_and_umax_8.S - arm/sync_fetch_and_umin_4.S - arm/sync_fetch_and_umin_8.S - arm/sync_fetch_and_xor_4.S - arm/sync_fetch_and_xor_8.S arm/sync_synchronize.S arm/udivmodsi4.S arm/udivsi3.S @@ -294,7 +282,32 @@ set(aarch64_SOURCES trunctfsf2.c ${GENERIC_SOURCES}) -set(armhf_SOURCES +# These are sources for the ARM platform that require Thumb2 instructions +# support. +set(arm_THUMB_SOURCES + arm/sync_fetch_and_add_4.S + arm/sync_fetch_and_add_8.S + arm/sync_fetch_and_and_4.S + arm/sync_fetch_and_and_8.S + arm/sync_fetch_and_max_4.S + arm/sync_fetch_and_max_8.S + arm/sync_fetch_and_min_4.S + arm/sync_fetch_and_min_8.S + arm/sync_fetch_and_nand_4.S + arm/sync_fetch_and_nand_8.S + arm/sync_fetch_and_or_4.S + arm/sync_fetch_and_or_8.S + arm/sync_fetch_and_sub_4.S + arm/sync_fetch_and_sub_8.S + arm/sync_fetch_and_umax_4.S + arm/sync_fetch_and_umax_8.S + arm/sync_fetch_and_umin_4.S + arm/sync_fetch_and_umin_8.S + arm/sync_fetch_and_xor_4.S + arm/sync_fetch_and_xor_8.S) + +# These are sources for the ARM platform that require VFP instructions support. +set(arm_VFP_SOURCES arm/adddf3vfp.S arm/addsf3vfp.S arm/divdf3vfp.S @@ -320,6 +333,8 @@ set(armhf_SOURCES arm/ltsf2vfp.S arm/muldf3vfp.S arm/mulsf3vfp.S + arm/negdf2vfp.S + arm/negsf2vfp.S arm/nedf2vfp.S arm/nesf2vfp.S arm/restore_vfp_d8_d15_regs.S @@ -328,22 +343,31 @@ set(armhf_SOURCES arm/subsf3vfp.S arm/truncdfsf2vfp.S arm/unorddf2vfp.S - arm/unordsf2vfp.S - ${arm_SOURCES}) -set(armv7_SOURCES ${arm_SOURCES}) -set(armv7s_SOURCES ${arm_SOURCES}) + arm/unordsf2vfp.S) + +set(arm_SOURCES ${arm_GENERIC_SOURCES}) +set(armhf_SOURCES ${arm_GENERIC_SOURCES} ${arm_VFP_SOURCES}) +set(armv7_SOURCES ${arm_GENERIC_SOURCES} ${arm_VFP_SOURCES} ${arm_THUMB_SOURCES}) +set(armv7s_SOURCES ${arm_GENERIC_SOURCES} ${arm_VFP_SOURCES} ${arm_THUMB_SOURCES}) set(arm64_SOURCES ${aarch64_SOURCES}) # macho_embedded archs set(armv6m_SOURCES ${GENERIC_SOURCES}) -set(armv7m_SOURCES ${arm_SOURCES}) -set(armv7em_SOURCES ${arm_SOURCES}) +set(armv7m_SOURCES ${arm_GENERIC_SOURCES} ${arm_THUMB_SOURCES}) +set(armv7em_SOURCES ${arm_GENERIC_SOURCES} ${arm_THUMB_SOURCES}) set(mips_SOURCES ${GENERIC_SOURCES}) set(mipsel_SOURCES ${mips_SOURCES}) set(mips64_SOURCES ${mips_SOURCES}) set(mips64el_SOURCES ${mips_SOURCES}) +set(powerpc_SOURCES ${GENERIC_SOURCES}) +set(powerpc64_SOURCES ${GENERIC_SOURCES}) +set(powerpc64le_SOURCES ${GENERIC_SOURCES}) + +set(wasm32_SOURCES ${GENERIC_SOURCES}) +set(wasm64_SOURCES ${GENERIC_SOURCES}) + add_custom_target(builtins) if (APPLE) @@ -351,6 +375,8 @@ if (APPLE) add_subdirectory(macho_embedded) darwin_add_builtin_libraries(${BUILTIN_SUPPORTED_OS}) else () + append_string_if(COMPILER_RT_HAS_STD_C99_FLAG -std=c99 maybe_stdc99) + foreach (arch ${BUILTIN_SUPPORTED_ARCH}) if (CAN_TARGET_${arch}) # Filter out generic versions of routines that are re-implemented in @@ -366,16 +392,14 @@ else () # Rust: don't insert a reference to MSVCRT.lib/etc if (MSVC) - set(_cflags -Zl) - else () - set(_cflags -std=c99) + set(maybe_zl -Zl) endif () add_compiler_rt_runtime(clang_rt.builtins STATIC ARCHS ${arch} SOURCES ${${arch}_SOURCES} - CFLAGS ${_cflags} + CFLAGS ${maybe_stdc99} ${maybe_zl} PARENT_TARGET builtins) endif () endforeach () diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7.txt b/src/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7.txt index 21cd778eb3..6aa542f7fe 100644 --- a/src/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7.txt +++ b/src/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7.txt @@ -1,3 +1,6 @@ +absvti2 +addtf3 +addvti3 aeabi_cdcmp aeabi_cdcmpeq_check_nan aeabi_cfcmp @@ -15,57 +18,13 @@ aeabi_memmove aeabi_memset aeabi_uidivmod aeabi_uldivmod -absvti2 -addtf3 -addvti3 ashlti3 ashrti3 clzti2 cmpti2 ctzti2 -divti3 divtf3 -ffsti2 -fixdfti -fixsfti -fixunsdfti -fixunssfti -fixunsxfti -fixxfti -floattidf -floattisf -floattixf -floatuntidf -floatuntisf -floatuntixf -lshrti3 -modti3 -muloti4 -multi3 -multf3 -mulvti3 -negti2 -negvti2 -parityti2 -popcountti2 -powitf2 -subvti3 -subtf3 -trampoline_setup -ucmpti2 -udivmodti4 -udivti3 -umodti3 -absvti2 -addtf3 -addvti3 -ashlti3 -ashrti3 -clzti2 -cmpti2 -ctzti2 divti3 -divtf3 ffsti2 fixdfti fixsfti @@ -81,17 +40,16 @@ floatuntisf floatuntixf lshrti3 modti3 -muloti4 -multi3 multf3 +multi3 mulvti3 negti2 negvti2 parityti2 popcountti2 powitf2 -subvti3 subtf3 +subvti3 trampoline_setup ucmpti2 udivmodti4 diff --git a/src/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7s.txt b/src/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7s.txt index 21cd778eb3..28167aa4c5 100644 --- a/src/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7s.txt +++ b/src/compiler-rt/lib/builtins/Darwin-excludes/ios-armv7s.txt @@ -1,3 +1,6 @@ +absvti2 +addtf3 +addvti3 aeabi_cdcmp aeabi_cdcmpeq_check_nan aeabi_cfcmp @@ -15,57 +18,13 @@ aeabi_memmove aeabi_memset aeabi_uidivmod aeabi_uldivmod -absvti2 -addtf3 -addvti3 ashlti3 ashrti3 clzti2 cmpti2 ctzti2 -divti3 divtf3 -ffsti2 -fixdfti -fixsfti -fixunsdfti -fixunssfti -fixunsxfti -fixxfti -floattidf -floattisf -floattixf -floatuntidf -floatuntisf -floatuntixf -lshrti3 -modti3 -muloti4 -multi3 -multf3 -mulvti3 -negti2 -negvti2 -parityti2 -popcountti2 -powitf2 -subvti3 -subtf3 -trampoline_setup -ucmpti2 -udivmodti4 -udivti3 -umodti3 -absvti2 -addtf3 -addvti3 -ashlti3 -ashrti3 -clzti2 -cmpti2 -ctzti2 divti3 -divtf3 ffsti2 fixdfti fixsfti @@ -81,17 +40,16 @@ floatuntisf floatuntixf lshrti3 modti3 -muloti4 +multf multi3 -multf3 mulvti3 negti2 negvti2 parityti2 popcountti2 powitf2 -subvti3 subtf3 +subvti3 trampoline_setup ucmpti2 udivmodti4 diff --git a/src/compiler-rt/lib/builtins/arm/adddf3vfp.S b/src/compiler-rt/lib/builtins/arm/adddf3vfp.S index 2825ae92cd..f4c00a03e0 100644 --- a/src/compiler-rt/lib/builtins/arm/adddf3vfp.S +++ b/src/compiler-rt/lib/builtins/arm/adddf3vfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__adddf3vfp) vmov r0, r1, d6 // move result back to r0/r1 pair bx lr END_COMPILERRT_FUNCTION(__adddf3vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/addsf3vfp.S b/src/compiler-rt/lib/builtins/arm/addsf3vfp.S index bff5a7e0fb..af40c1cc92 100644 --- a/src/compiler-rt/lib/builtins/arm/addsf3vfp.S +++ b/src/compiler-rt/lib/builtins/arm/addsf3vfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__addsf3vfp) vmov r0, s14 // move result back to r0 bx lr END_COMPILERRT_FUNCTION(__addsf3vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S b/src/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S index 036a6f542f..8008f5fca2 100644 --- a/src/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S +++ b/src/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S @@ -94,3 +94,5 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cdrcmple) b __aeabi_cdcmple END_COMPILERRT_FUNCTION(__aeabi_cdrcmple) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S b/src/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S index 43594e5c39..274baf7aec 100644 --- a/src/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S +++ b/src/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S @@ -89,3 +89,5 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cfrcmple) b __aeabi_cfcmple END_COMPILERRT_FUNCTION(__aeabi_cfrcmple) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_dcmp.S b/src/compiler-rt/lib/builtins/arm/aeabi_dcmp.S index 310c35b749..43e439268d 100644 --- a/src/compiler-rt/lib/builtins/arm/aeabi_dcmp.S +++ b/src/compiler-rt/lib/builtins/arm/aeabi_dcmp.S @@ -38,3 +38,6 @@ DEFINE_AEABI_DCMP(lt) DEFINE_AEABI_DCMP(le) DEFINE_AEABI_DCMP(ge) DEFINE_AEABI_DCMP(gt) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_fcmp.S b/src/compiler-rt/lib/builtins/arm/aeabi_fcmp.S index 55f49a2b5a..0a1d92a60b 100644 --- a/src/compiler-rt/lib/builtins/arm/aeabi_fcmp.S +++ b/src/compiler-rt/lib/builtins/arm/aeabi_fcmp.S @@ -38,3 +38,6 @@ DEFINE_AEABI_FCMP(lt) DEFINE_AEABI_FCMP(le) DEFINE_AEABI_FCMP(ge) DEFINE_AEABI_FCMP(gt) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_idivmod.S b/src/compiler-rt/lib/builtins/arm/aeabi_idivmod.S index 384add3827..2fcad862f7 100644 --- a/src/compiler-rt/lib/builtins/arm/aeabi_idivmod.S +++ b/src/compiler-rt/lib/builtins/arm/aeabi_idivmod.S @@ -26,3 +26,6 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_idivmod) add sp, sp, #4 pop { pc } END_COMPILERRT_FUNCTION(__aeabi_idivmod) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_ldivmod.S b/src/compiler-rt/lib/builtins/arm/aeabi_ldivmod.S index ad06f1de2a..9f161f3007 100644 --- a/src/compiler-rt/lib/builtins/arm/aeabi_ldivmod.S +++ b/src/compiler-rt/lib/builtins/arm/aeabi_ldivmod.S @@ -29,3 +29,6 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_ldivmod) add sp, sp, #16 pop {r11, pc} END_COMPILERRT_FUNCTION(__aeabi_ldivmod) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_memcmp.S b/src/compiler-rt/lib/builtins/arm/aeabi_memcmp.S index 051ce435ba..8f49d06891 100644 --- a/src/compiler-rt/lib/builtins/arm/aeabi_memcmp.S +++ b/src/compiler-rt/lib/builtins/arm/aeabi_memcmp.S @@ -18,3 +18,6 @@ END_COMPILERRT_FUNCTION(__aeabi_memcmp) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp4, __aeabi_memcmp) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp8, __aeabi_memcmp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_memcpy.S b/src/compiler-rt/lib/builtins/arm/aeabi_memcpy.S index cf02332490..bc84863642 100644 --- a/src/compiler-rt/lib/builtins/arm/aeabi_memcpy.S +++ b/src/compiler-rt/lib/builtins/arm/aeabi_memcpy.S @@ -18,3 +18,6 @@ END_COMPILERRT_FUNCTION(__aeabi_memcpy) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy4, __aeabi_memcpy) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy8, __aeabi_memcpy) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_memmove.S b/src/compiler-rt/lib/builtins/arm/aeabi_memmove.S index 4dda06f75d..1bf08c0d5b 100644 --- a/src/compiler-rt/lib/builtins/arm/aeabi_memmove.S +++ b/src/compiler-rt/lib/builtins/arm/aeabi_memmove.S @@ -18,3 +18,6 @@ END_COMPILERRT_FUNCTION(__aeabi_memmove) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove4, __aeabi_memmove) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove8, __aeabi_memmove) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_memset.S b/src/compiler-rt/lib/builtins/arm/aeabi_memset.S index c8b49c7809..c1d655a559 100644 --- a/src/compiler-rt/lib/builtins/arm/aeabi_memset.S +++ b/src/compiler-rt/lib/builtins/arm/aeabi_memset.S @@ -32,3 +32,5 @@ END_COMPILERRT_FUNCTION(__aeabi_memclr) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr4, __aeabi_memclr) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr8, __aeabi_memclr) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S b/src/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S index 8ea474d91c..e1e12d97aa 100644 --- a/src/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S +++ b/src/compiler-rt/lib/builtins/arm/aeabi_uidivmod.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_uidivmod) add sp, sp, #4 pop { pc } END_COMPILERRT_FUNCTION(__aeabi_uidivmod) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/aeabi_uldivmod.S b/src/compiler-rt/lib/builtins/arm/aeabi_uldivmod.S index 4e1f8e2a67..e8aaef282e 100644 --- a/src/compiler-rt/lib/builtins/arm/aeabi_uldivmod.S +++ b/src/compiler-rt/lib/builtins/arm/aeabi_uldivmod.S @@ -29,3 +29,6 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_uldivmod) add sp, sp, #16 pop {r11, pc} END_COMPILERRT_FUNCTION(__aeabi_uldivmod) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/bswapdi2.S b/src/compiler-rt/lib/builtins/arm/bswapdi2.S index 86f3bba8c2..fb226cea24 100644 --- a/src/compiler-rt/lib/builtins/arm/bswapdi2.S +++ b/src/compiler-rt/lib/builtins/arm/bswapdi2.S @@ -45,3 +45,6 @@ DEFINE_COMPILERRT_FUNCTION(__bswapdi2) mov r1, r2 // r1 = r2 = rev(r0) JMP(lr) END_COMPILERRT_FUNCTION(__bswapdi2) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/bswapsi2.S b/src/compiler-rt/lib/builtins/arm/bswapsi2.S index 59ba8158fd..553c3c2e39 100644 --- a/src/compiler-rt/lib/builtins/arm/bswapsi2.S +++ b/src/compiler-rt/lib/builtins/arm/bswapsi2.S @@ -37,3 +37,6 @@ DEFINE_COMPILERRT_FUNCTION(__bswapsi2) #endif JMP(lr) END_COMPILERRT_FUNCTION(__bswapsi2) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/clzdi2.S b/src/compiler-rt/lib/builtins/arm/clzdi2.S index a55abac046..6068c176fd 100644 --- a/src/compiler-rt/lib/builtins/arm/clzdi2.S +++ b/src/compiler-rt/lib/builtins/arm/clzdi2.S @@ -95,3 +95,6 @@ DEFINE_COMPILERRT_FUNCTION(__clzdi2) JMP(lr) #endif // __ARM_FEATURE_CLZ END_COMPILERRT_FUNCTION(__clzdi2) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/clzsi2.S b/src/compiler-rt/lib/builtins/arm/clzsi2.S index 1cd379bfb0..c2ba3a8cfc 100644 --- a/src/compiler-rt/lib/builtins/arm/clzsi2.S +++ b/src/compiler-rt/lib/builtins/arm/clzsi2.S @@ -74,3 +74,6 @@ DEFINE_COMPILERRT_FUNCTION(__clzsi2) JMP(lr) #endif // __ARM_FEATURE_CLZ END_COMPILERRT_FUNCTION(__clzsi2) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/comparesf2.S b/src/compiler-rt/lib/builtins/arm/comparesf2.S index cf71d36e05..52597b673f 100644 --- a/src/compiler-rt/lib/builtins/arm/comparesf2.S +++ b/src/compiler-rt/lib/builtins/arm/comparesf2.S @@ -146,3 +146,6 @@ DEFINE_COMPILERRT_FUNCTION(__unordsf2) END_COMPILERRT_FUNCTION(__unordsf2) DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_fcmpun, __unordsf2) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/divdf3vfp.S b/src/compiler-rt/lib/builtins/arm/divdf3vfp.S index 6eebef167a..928f53809f 100644 --- a/src/compiler-rt/lib/builtins/arm/divdf3vfp.S +++ b/src/compiler-rt/lib/builtins/arm/divdf3vfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__divdf3vfp) vmov r0, r1, d5 // move result back to r0/r1 pair bx lr END_COMPILERRT_FUNCTION(__divdf3vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/divmodsi4.S b/src/compiler-rt/lib/builtins/arm/divmodsi4.S index 646b9ab78f..999c310ec8 100644 --- a/src/compiler-rt/lib/builtins/arm/divmodsi4.S +++ b/src/compiler-rt/lib/builtins/arm/divmodsi4.S @@ -72,3 +72,6 @@ LOCAL_LABEL(divzero): CLEAR_FRAME_AND_RETURN #endif END_COMPILERRT_FUNCTION(__divmodsi4) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/divsf3vfp.S b/src/compiler-rt/lib/builtins/arm/divsf3vfp.S index fdbaebc883..a2e297f701 100644 --- a/src/compiler-rt/lib/builtins/arm/divsf3vfp.S +++ b/src/compiler-rt/lib/builtins/arm/divsf3vfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__divsf3vfp) vmov r0, s13 // move result back to r0 bx lr END_COMPILERRT_FUNCTION(__divsf3vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/divsi3.S b/src/compiler-rt/lib/builtins/arm/divsi3.S index adf8f94fc7..7e23ba4fc2 100644 --- a/src/compiler-rt/lib/builtins/arm/divsi3.S +++ b/src/compiler-rt/lib/builtins/arm/divsi3.S @@ -63,3 +63,6 @@ ESTABLISH_FRAME CLEAR_FRAME_AND_RETURN #endif END_COMPILERRT_FUNCTION(__divsi3) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/eqdf2vfp.S b/src/compiler-rt/lib/builtins/arm/eqdf2vfp.S index 7f2fbc3072..95e6bb3633 100644 --- a/src/compiler-rt/lib/builtins/arm/eqdf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/eqdf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__eqdf2vfp) movne r0, #0 bx lr END_COMPILERRT_FUNCTION(__eqdf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/eqsf2vfp.S b/src/compiler-rt/lib/builtins/arm/eqsf2vfp.S index a318b336ae..fbac139c19 100644 --- a/src/compiler-rt/lib/builtins/arm/eqsf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/eqsf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__eqsf2vfp) movne r0, #0 bx lr END_COMPILERRT_FUNCTION(__eqsf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/extendsfdf2vfp.S b/src/compiler-rt/lib/builtins/arm/extendsfdf2vfp.S index b998e58945..563bf92afc 100644 --- a/src/compiler-rt/lib/builtins/arm/extendsfdf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/extendsfdf2vfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__extendsfdf2vfp) vmov r0, r1, d7 // return result in r0/r1 pair bx lr END_COMPILERRT_FUNCTION(__extendsfdf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/fixdfsivfp.S b/src/compiler-rt/lib/builtins/arm/fixdfsivfp.S index e3bd8e05e0..8263ff942f 100644 --- a/src/compiler-rt/lib/builtins/arm/fixdfsivfp.S +++ b/src/compiler-rt/lib/builtins/arm/fixdfsivfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__fixdfsivfp) vmov r0, s15 // move s15 to result register bx lr END_COMPILERRT_FUNCTION(__fixdfsivfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/fixsfsivfp.S b/src/compiler-rt/lib/builtins/arm/fixsfsivfp.S index 3d0d0f56d2..c7c3b81178 100644 --- a/src/compiler-rt/lib/builtins/arm/fixsfsivfp.S +++ b/src/compiler-rt/lib/builtins/arm/fixsfsivfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__fixsfsivfp) vmov r0, s15 // move s15 to result register bx lr END_COMPILERRT_FUNCTION(__fixsfsivfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/fixunsdfsivfp.S b/src/compiler-rt/lib/builtins/arm/fixunsdfsivfp.S index 35dda5b9b0..9cc1e62869 100644 --- a/src/compiler-rt/lib/builtins/arm/fixunsdfsivfp.S +++ b/src/compiler-rt/lib/builtins/arm/fixunsdfsivfp.S @@ -25,3 +25,6 @@ DEFINE_COMPILERRT_FUNCTION(__fixunsdfsivfp) vmov r0, s15 // move s15 to result register bx lr END_COMPILERRT_FUNCTION(__fixunsdfsivfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/fixunssfsivfp.S b/src/compiler-rt/lib/builtins/arm/fixunssfsivfp.S index 5c3a7d926f..79d7082291 100644 --- a/src/compiler-rt/lib/builtins/arm/fixunssfsivfp.S +++ b/src/compiler-rt/lib/builtins/arm/fixunssfsivfp.S @@ -25,3 +25,6 @@ DEFINE_COMPILERRT_FUNCTION(__fixunssfsivfp) vmov r0, s15 // move s15 to result register bx lr END_COMPILERRT_FUNCTION(__fixunssfsivfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/floatsidfvfp.S b/src/compiler-rt/lib/builtins/arm/floatsidfvfp.S index d69184914c..7623f26c6e 100644 --- a/src/compiler-rt/lib/builtins/arm/floatsidfvfp.S +++ b/src/compiler-rt/lib/builtins/arm/floatsidfvfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__floatsidfvfp) vmov r0, r1, d7 // move d7 to result register pair r0/r1 bx lr END_COMPILERRT_FUNCTION(__floatsidfvfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/floatsisfvfp.S b/src/compiler-rt/lib/builtins/arm/floatsisfvfp.S index 4a0cb39d0e..c73dfac13e 100644 --- a/src/compiler-rt/lib/builtins/arm/floatsisfvfp.S +++ b/src/compiler-rt/lib/builtins/arm/floatsisfvfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__floatsisfvfp) vmov r0, s15 // move s15 to result register bx lr END_COMPILERRT_FUNCTION(__floatsisfvfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/floatunssidfvfp.S b/src/compiler-rt/lib/builtins/arm/floatunssidfvfp.S index d92969ea34..2a59fdb830 100644 --- a/src/compiler-rt/lib/builtins/arm/floatunssidfvfp.S +++ b/src/compiler-rt/lib/builtins/arm/floatunssidfvfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__floatunssidfvfp) vmov r0, r1, d7 // move d7 to result register pair r0/r1 bx lr END_COMPILERRT_FUNCTION(__floatunssidfvfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/floatunssisfvfp.S b/src/compiler-rt/lib/builtins/arm/floatunssisfvfp.S index f6aeba56ae..c096263c1b 100644 --- a/src/compiler-rt/lib/builtins/arm/floatunssisfvfp.S +++ b/src/compiler-rt/lib/builtins/arm/floatunssisfvfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__floatunssisfvfp) vmov r0, s15 // move s15 to result register bx lr END_COMPILERRT_FUNCTION(__floatunssisfvfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/gedf2vfp.S b/src/compiler-rt/lib/builtins/arm/gedf2vfp.S index 9e23527017..72f13ef4e7 100644 --- a/src/compiler-rt/lib/builtins/arm/gedf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/gedf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__gedf2vfp) movlt r0, #0 bx lr END_COMPILERRT_FUNCTION(__gedf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/gesf2vfp.S b/src/compiler-rt/lib/builtins/arm/gesf2vfp.S index 0ff6084778..c9ee52c9c4 100644 --- a/src/compiler-rt/lib/builtins/arm/gesf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/gesf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__gesf2vfp) movlt r0, #0 bx lr END_COMPILERRT_FUNCTION(__gesf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/gtdf2vfp.S b/src/compiler-rt/lib/builtins/arm/gtdf2vfp.S index 3dc5d5b592..c7f277552f 100644 --- a/src/compiler-rt/lib/builtins/arm/gtdf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/gtdf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__gtdf2vfp) movle r0, #0 bx lr END_COMPILERRT_FUNCTION(__gtdf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/gtsf2vfp.S b/src/compiler-rt/lib/builtins/arm/gtsf2vfp.S index ddd843acf5..7d49e4564a 100644 --- a/src/compiler-rt/lib/builtins/arm/gtsf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/gtsf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__gtsf2vfp) movle r0, #0 bx lr END_COMPILERRT_FUNCTION(__gtsf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/ledf2vfp.S b/src/compiler-rt/lib/builtins/arm/ledf2vfp.S index b06ff6db5a..ca5b553f11 100644 --- a/src/compiler-rt/lib/builtins/arm/ledf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/ledf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__ledf2vfp) movhi r0, #0 bx lr END_COMPILERRT_FUNCTION(__ledf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/lesf2vfp.S b/src/compiler-rt/lib/builtins/arm/lesf2vfp.S index 9b33c0c536..f25422ece8 100644 --- a/src/compiler-rt/lib/builtins/arm/lesf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/lesf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__lesf2vfp) movhi r0, #0 bx lr END_COMPILERRT_FUNCTION(__lesf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/ltdf2vfp.S b/src/compiler-rt/lib/builtins/arm/ltdf2vfp.S index 9f794b026a..6e2c0997c0 100644 --- a/src/compiler-rt/lib/builtins/arm/ltdf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/ltdf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__ltdf2vfp) movpl r0, #0 bx lr END_COMPILERRT_FUNCTION(__ltdf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/ltsf2vfp.S b/src/compiler-rt/lib/builtins/arm/ltsf2vfp.S index ba190d9d8d..95febb6067 100644 --- a/src/compiler-rt/lib/builtins/arm/ltsf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/ltsf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__ltsf2vfp) movpl r0, #0 bx lr END_COMPILERRT_FUNCTION(__ltsf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/modsi3.S b/src/compiler-rt/lib/builtins/arm/modsi3.S index 295a227d86..1d302edc67 100644 --- a/src/compiler-rt/lib/builtins/arm/modsi3.S +++ b/src/compiler-rt/lib/builtins/arm/modsi3.S @@ -61,3 +61,6 @@ LOCAL_LABEL(divzero): CLEAR_FRAME_AND_RETURN #endif END_COMPILERRT_FUNCTION(__modsi3) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/muldf3vfp.S b/src/compiler-rt/lib/builtins/arm/muldf3vfp.S index 636cc711ac..f638de1ad2 100644 --- a/src/compiler-rt/lib/builtins/arm/muldf3vfp.S +++ b/src/compiler-rt/lib/builtins/arm/muldf3vfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__muldf3vfp) vmov r0, r1, d6 // move result back to r0/r1 pair bx lr END_COMPILERRT_FUNCTION(__muldf3vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/mulsf3vfp.S b/src/compiler-rt/lib/builtins/arm/mulsf3vfp.S index 7f4008266b..bef58d3a0c 100644 --- a/src/compiler-rt/lib/builtins/arm/mulsf3vfp.S +++ b/src/compiler-rt/lib/builtins/arm/mulsf3vfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__mulsf3vfp) vmov r0, s13 // move result back to r0 bx lr END_COMPILERRT_FUNCTION(__mulsf3vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/nedf2vfp.S b/src/compiler-rt/lib/builtins/arm/nedf2vfp.S index 7ab2f5501c..78cf529d66 100644 --- a/src/compiler-rt/lib/builtins/arm/nedf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/nedf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__nedf2vfp) moveq r0, #0 bx lr END_COMPILERRT_FUNCTION(__nedf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/negdf2vfp.S b/src/compiler-rt/lib/builtins/arm/negdf2vfp.S index 56d73c6761..01c8ba6a12 100644 --- a/src/compiler-rt/lib/builtins/arm/negdf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/negdf2vfp.S @@ -21,3 +21,6 @@ DEFINE_COMPILERRT_FUNCTION(__negdf2vfp) eor r1, r1, #-2147483648 // flip sign bit on double in r0/r1 pair bx lr END_COMPILERRT_FUNCTION(__negdf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/negsf2vfp.S b/src/compiler-rt/lib/builtins/arm/negsf2vfp.S index a6e32e1ff8..797abb32ea 100644 --- a/src/compiler-rt/lib/builtins/arm/negsf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/negsf2vfp.S @@ -21,3 +21,6 @@ DEFINE_COMPILERRT_FUNCTION(__negsf2vfp) eor r0, r0, #-2147483648 // flip sign bit on float in r0 bx lr END_COMPILERRT_FUNCTION(__negsf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/nesf2vfp.S b/src/compiler-rt/lib/builtins/arm/nesf2vfp.S index 9fe8ecdefb..554d3e4675 100644 --- a/src/compiler-rt/lib/builtins/arm/nesf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/nesf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__nesf2vfp) moveq r0, #0 bx lr END_COMPILERRT_FUNCTION(__nesf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/restore_vfp_d8_d15_regs.S b/src/compiler-rt/lib/builtins/arm/restore_vfp_d8_d15_regs.S index 0f6ea51361..0692cf3e1b 100644 --- a/src/compiler-rt/lib/builtins/arm/restore_vfp_d8_d15_regs.S +++ b/src/compiler-rt/lib/builtins/arm/restore_vfp_d8_d15_regs.S @@ -31,3 +31,5 @@ DEFINE_COMPILERRT_PRIVATE_FUNCTION(__restore_vfp_d8_d15_regs) bx lr // return to prolog END_COMPILERRT_FUNCTION(__restore_vfp_d8_d15_regs) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/save_vfp_d8_d15_regs.S b/src/compiler-rt/lib/builtins/arm/save_vfp_d8_d15_regs.S index f1d90e7580..544dd5467a 100644 --- a/src/compiler-rt/lib/builtins/arm/save_vfp_d8_d15_regs.S +++ b/src/compiler-rt/lib/builtins/arm/save_vfp_d8_d15_regs.S @@ -31,3 +31,5 @@ DEFINE_COMPILERRT_PRIVATE_FUNCTION(__save_vfp_d8_d15_regs) bx lr // return to prolog END_COMPILERRT_FUNCTION(__save_vfp_d8_d15_regs) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/subdf3vfp.S b/src/compiler-rt/lib/builtins/arm/subdf3vfp.S index 5f3c0f70db..1fc7d18c3d 100644 --- a/src/compiler-rt/lib/builtins/arm/subdf3vfp.S +++ b/src/compiler-rt/lib/builtins/arm/subdf3vfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__subdf3vfp) vmov r0, r1, d6 // move result back to r0/r1 pair bx lr END_COMPILERRT_FUNCTION(__subdf3vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/subsf3vfp.S b/src/compiler-rt/lib/builtins/arm/subsf3vfp.S index d6e06df519..11fe386cd0 100644 --- a/src/compiler-rt/lib/builtins/arm/subsf3vfp.S +++ b/src/compiler-rt/lib/builtins/arm/subsf3vfp.S @@ -25,3 +25,6 @@ DEFINE_COMPILERRT_FUNCTION(__subsf3vfp) vmov r0, s14 // move result back to r0 bx lr END_COMPILERRT_FUNCTION(__subsf3vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/switch16.S b/src/compiler-rt/lib/builtins/arm/switch16.S index 3c3a6b1061..df9e38e176 100644 --- a/src/compiler-rt/lib/builtins/arm/switch16.S +++ b/src/compiler-rt/lib/builtins/arm/switch16.S @@ -42,3 +42,5 @@ DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switch16) bx ip // jump to computed label END_COMPILERRT_FUNCTION(__switch16) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/switch32.S b/src/compiler-rt/lib/builtins/arm/switch32.S index b38cd2b764..d97b536143 100644 --- a/src/compiler-rt/lib/builtins/arm/switch32.S +++ b/src/compiler-rt/lib/builtins/arm/switch32.S @@ -42,3 +42,5 @@ DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switch32) bx ip // jump to computed label END_COMPILERRT_FUNCTION(__switch32) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/switch8.S b/src/compiler-rt/lib/builtins/arm/switch8.S index d7c20423de..4d9e0eaff8 100644 --- a/src/compiler-rt/lib/builtins/arm/switch8.S +++ b/src/compiler-rt/lib/builtins/arm/switch8.S @@ -40,3 +40,5 @@ DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switch8) bx ip // jump to computed label END_COMPILERRT_FUNCTION(__switch8) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/switchu8.S b/src/compiler-rt/lib/builtins/arm/switchu8.S index 1844f11c60..4ffe35f054 100644 --- a/src/compiler-rt/lib/builtins/arm/switchu8.S +++ b/src/compiler-rt/lib/builtins/arm/switchu8.S @@ -40,3 +40,5 @@ DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switchu8) bx ip // jump to computed label END_COMPILERRT_FUNCTION(__switchu8) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S index 54c33e2d26..7877d6c46c 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_add_4.S @@ -19,3 +19,5 @@ SYNC_OP_4(add_4) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_add_8.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_add_8.S index 5724bb148b..1df07a342a 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_add_8.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_add_8.S @@ -22,3 +22,5 @@ SYNC_OP_8(add_8) #endif +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_and_4.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_and_4.S index e2b77a1a87..720ff02279 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_and_4.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_and_4.S @@ -17,3 +17,6 @@ #define and_4(rD, rN, rM) and rD, rN, rM SYNC_OP_4(and_4) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_and_8.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_and_8.S index a74163a860..4f7b5ca7ab 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_and_8.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_and_8.S @@ -21,3 +21,6 @@ SYNC_OP_8(and_8) #endif + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_max_4.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_max_4.S index 01e4f444c2..43da9c7d40 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_max_4.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_max_4.S @@ -18,3 +18,5 @@ SYNC_OP_4(max_4) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_max_8.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_max_8.S index 1eef2b2236..898fc6202a 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_max_8.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_max_8.S @@ -19,3 +19,6 @@ SYNC_OP_8(max_8) #endif + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_min_4.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_min_4.S index 015626b63d..bba31a03aa 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_min_4.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_min_4.S @@ -18,3 +18,5 @@ SYNC_OP_4(min_4) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_min_8.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_min_8.S index ad5cce0754..e7ccf9fb60 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_min_8.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_min_8.S @@ -19,3 +19,6 @@ SYNC_OP_8(min_8) #endif + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_4.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_4.S index b32a314b39..c13dd39458 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_4.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_4.S @@ -18,3 +18,5 @@ SYNC_OP_4(nand_4) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_8.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_8.S index a2c17c09c0..e8107ab3a3 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_8.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_nand_8.S @@ -22,3 +22,5 @@ SYNC_OP_8(nand_8) #endif +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_or_4.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_or_4.S index f2e08576aa..6726571a94 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_or_4.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_or_4.S @@ -18,3 +18,5 @@ SYNC_OP_4(or_4) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_or_8.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_or_8.S index 87b940bf62..f7f162c7c3 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_or_8.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_or_8.S @@ -22,3 +22,5 @@ SYNC_OP_8(or_8) #endif +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_4.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_4.S index 460b2bc1ed..b9326b14cd 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_4.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_4.S @@ -19,3 +19,5 @@ SYNC_OP_4(sub_4) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_8.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_8.S index a8035a2768..6ce743e5ee 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_8.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_sub_8.S @@ -22,3 +22,5 @@ SYNC_OP_8(sub_8) #endif +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_4.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_4.S index c591530319..b8d19ff350 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_4.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_4.S @@ -18,3 +18,5 @@ SYNC_OP_4(umax_4) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_8.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_8.S index d9b7965e52..34442fd774 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_8.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umax_8.S @@ -19,3 +19,6 @@ SYNC_OP_8(umax_8) #endif + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_4.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_4.S index 9f3896fca8..0998e3e10f 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_4.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_4.S @@ -18,3 +18,5 @@ SYNC_OP_4(umin_4) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_8.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_8.S index 7bf5e23565..558f913905 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_8.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_umin_8.S @@ -19,3 +19,6 @@ SYNC_OP_8(umin_8) #endif + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_4.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_4.S index 7e7c90c962..824f491468 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_4.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_4.S @@ -18,3 +18,5 @@ SYNC_OP_4(xor_4) +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_8.S b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_8.S index ea9aa6d4b0..073fb9c20f 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_8.S +++ b/src/compiler-rt/lib/builtins/arm/sync_fetch_and_xor_8.S @@ -22,3 +22,5 @@ SYNC_OP_8(xor_8) #endif +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/sync_synchronize.S b/src/compiler-rt/lib/builtins/arm/sync_synchronize.S index 178f24534c..61d1db910f 100644 --- a/src/compiler-rt/lib/builtins/arm/sync_synchronize.S +++ b/src/compiler-rt/lib/builtins/arm/sync_synchronize.S @@ -33,3 +33,6 @@ END_COMPILERRT_FUNCTION(__sync_synchronize) .subsections_via_symbols #endif + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S b/src/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S index fa4362c45e..04287ad27c 100644 --- a/src/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S @@ -24,3 +24,6 @@ DEFINE_COMPILERRT_FUNCTION(__truncdfsf2vfp) vmov r0, s15 // return result in r0 bx lr END_COMPILERRT_FUNCTION(__truncdfsf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/udivmodsi4.S b/src/compiler-rt/lib/builtins/arm/udivmodsi4.S index 85b84936c4..1ad8ee34bd 100644 --- a/src/compiler-rt/lib/builtins/arm/udivmodsi4.S +++ b/src/compiler-rt/lib/builtins/arm/udivmodsi4.S @@ -182,3 +182,6 @@ LOCAL_LABEL(divby0): #endif END_COMPILERRT_FUNCTION(__udivmodsi4) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/udivsi3.S b/src/compiler-rt/lib/builtins/arm/udivsi3.S index 165b2b58ac..085f8fb9e2 100644 --- a/src/compiler-rt/lib/builtins/arm/udivsi3.S +++ b/src/compiler-rt/lib/builtins/arm/udivsi3.S @@ -168,3 +168,6 @@ LOCAL_LABEL(divby0): #endif END_COMPILERRT_FUNCTION(__udivsi3) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/umodsi3.S b/src/compiler-rt/lib/builtins/arm/umodsi3.S index 9e7a148ce4..672487e81a 100644 --- a/src/compiler-rt/lib/builtins/arm/umodsi3.S +++ b/src/compiler-rt/lib/builtins/arm/umodsi3.S @@ -159,3 +159,6 @@ LOCAL_LABEL(divby0): #endif END_COMPILERRT_FUNCTION(__umodsi3) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/unorddf2vfp.S b/src/compiler-rt/lib/builtins/arm/unorddf2vfp.S index c4bea2d5ee..022dd7a978 100644 --- a/src/compiler-rt/lib/builtins/arm/unorddf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/unorddf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__unorddf2vfp) movvc r0, #0 bx lr END_COMPILERRT_FUNCTION(__unorddf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/arm/unordsf2vfp.S b/src/compiler-rt/lib/builtins/arm/unordsf2vfp.S index 886e965681..5ebdd3df55 100644 --- a/src/compiler-rt/lib/builtins/arm/unordsf2vfp.S +++ b/src/compiler-rt/lib/builtins/arm/unordsf2vfp.S @@ -27,3 +27,6 @@ DEFINE_COMPILERRT_FUNCTION(__unordsf2vfp) movvc r0, #0 bx lr END_COMPILERRT_FUNCTION(__unordsf2vfp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/assembly.h b/src/compiler-rt/lib/builtins/assembly.h index c28970534c..5fc74f68f6 100644 --- a/src/compiler-rt/lib/builtins/assembly.h +++ b/src/compiler-rt/lib/builtins/assembly.h @@ -30,6 +30,8 @@ #define SYMBOL_IS_FUNC(name) #define CONST_SECTION .const +#define NO_EXEC_STACK_DIRECTIVE + #elif defined(__ELF__) #define HIDDEN(name) .hidden name @@ -42,6 +44,12 @@ #endif #define CONST_SECTION .section .rodata +#if defined(__GNU__) || defined(__ANDROID__) || defined(__FreeBSD__) +#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits +#else +#define NO_EXEC_STACK_DIRECTIVE +#endif + #else // !__APPLE__ && !__ELF__ #define HIDDEN(name) @@ -54,6 +62,8 @@ .endef #define CONST_SECTION .section .rdata,"rd" +#define NO_EXEC_STACK_DIRECTIVE + #endif #if defined(__arm__) diff --git a/src/compiler-rt/lib/builtins/divtc3.c b/src/compiler-rt/lib/builtins/divtc3.c new file mode 100644 index 0000000000..04693df471 --- /dev/null +++ b/src/compiler-rt/lib/builtins/divtc3.c @@ -0,0 +1,60 @@ +/*===-- divtc3.c - Implement __divtc3 -------------------------------------=== + * + * 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 __divtc3 for the compiler_rt library. + * + *===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" +#include "int_math.h" + +/* Returns: the quotient of (a + ib) / (c + id) */ + +COMPILER_RT_ABI long double _Complex +__divtc3(long double __a, long double __b, long double __c, long double __d) +{ + int __ilogbw = 0; + long double __logbw = crt_logbl(crt_fmaxl(crt_fabsl(__c), crt_fabsl(__d))); + if (crt_isfinite(__logbw)) + { + __ilogbw = (int)__logbw; + __c = crt_scalbnl(__c, -__ilogbw); + __d = crt_scalbnl(__d, -__ilogbw); + } + long double __denom = __c * __c + __d * __d; + long double _Complex z; + __real__ z = crt_scalbnl((__a * __c + __b * __d) / __denom, -__ilogbw); + __imag__ z = crt_scalbnl((__b * __c - __a * __d) / __denom, -__ilogbw); + if (crt_isnan(__real__ z) && crt_isnan(__imag__ z)) + { + if ((__denom == 0.0) && (!crt_isnan(__a) || !crt_isnan(__b))) + { + __real__ z = crt_copysignl(CRT_INFINITY, __c) * __a; + __imag__ z = crt_copysignl(CRT_INFINITY, __c) * __b; + } + else if ((crt_isinf(__a) || crt_isinf(__b)) && + crt_isfinite(__c) && crt_isfinite(__d)) + { + __a = crt_copysignl(crt_isinf(__a) ? 1.0 : 0.0, __a); + __b = crt_copysignl(crt_isinf(__b) ? 1.0 : 0.0, __b); + __real__ z = CRT_INFINITY * (__a * __c + __b * __d); + __imag__ z = CRT_INFINITY * (__b * __c - __a * __d); + } + else if (crt_isinf(__logbw) && __logbw > 0.0 && + crt_isfinite(__a) && crt_isfinite(__b)) + { + __c = crt_copysignl(crt_isinf(__c) ? 1.0 : 0.0, __c); + __d = crt_copysignl(crt_isinf(__d) ? 1.0 : 0.0, __d); + __real__ z = 0.0 * (__a * __c + __b * __d); + __imag__ z = 0.0 * (__b * __c - __a * __d); + } + } + return z; +} diff --git a/src/compiler-rt/lib/builtins/gcc_personality_v0.c b/src/compiler-rt/lib/builtins/gcc_personality_v0.c index afe643c4bd..aba3865f7e 100644 --- a/src/compiler-rt/lib/builtins/gcc_personality_v0.c +++ b/src/compiler-rt/lib/builtins/gcc_personality_v0.c @@ -131,6 +131,26 @@ static uintptr_t readEncodedPointer(const uint8_t** data, uint8_t encoding) return result; } +#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ + !defined(__ARM_DWARF_EH__) +#define USING_ARM_EHABI 1 +_Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception *, + struct _Unwind_Context *); +#endif + +static inline _Unwind_Reason_Code +continueUnwind(struct _Unwind_Exception *exceptionObject, + struct _Unwind_Context *context) { +#if USING_ARM_EHABI + /* + * On ARM EHABI the personality routine is responsible for actually + * unwinding a single stack frame before returning (ARM EHABI Sec. 6.1). + */ + if (__gnu_unwind_frame(exceptionObject, context) != _URC_OK) + return _URC_FAILURE; +#endif + return _URC_CONTINUE_UNWIND; +} /* * The C compiler makes references to __gcc_personality_v0 in @@ -141,11 +161,17 @@ static uintptr_t readEncodedPointer(const uint8_t** data, uint8_t encoding) * throw through a C function compiled with -fexceptions. */ #if __USING_SJLJ_EXCEPTIONS__ -// the setjump-longjump based exceptions personality routine has a different name +/* the setjump-longjump based exceptions personality routine has a + * different name */ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_sj0(int version, _Unwind_Action actions, uint64_t exceptionClass, struct _Unwind_Exception* exceptionObject, struct _Unwind_Context *context) +#elif USING_ARM_EHABI +/* The ARM EHABI personality routine has a different signature. */ +COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( + _Unwind_State state, struct _Unwind_Exception *exceptionObject, + struct _Unwind_Context *context) #else COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(int version, _Unwind_Action actions, @@ -155,13 +181,19 @@ __gcc_personality_v0(int version, _Unwind_Action actions, { /* Since C does not have catch clauses, there is nothing to do during */ /* phase 1 (the search phase). */ - if ( actions & _UA_SEARCH_PHASE ) - return _URC_CONTINUE_UNWIND; - +#if USING_ARM_EHABI + /* After resuming from a cleanup we should also continue on to the next + * frame straight away. */ + if ((state & _US_ACTION_MASK) != _US_UNWIND_FRAME_STARTING) +#else + if ( actions & _UA_SEARCH_PHASE ) +#endif + return continueUnwind(exceptionObject, context); + /* There is nothing to do if there is no LSDA for this frame. */ const uint8_t* lsda = (uint8_t*)_Unwind_GetLanguageSpecificData(context); if ( lsda == (uint8_t*) 0 ) - return _URC_CONTINUE_UNWIND; + return continueUnwind(exceptionObject, context); uintptr_t pc = _Unwind_GetIP(context)-1; @@ -226,7 +258,8 @@ __gcc_personality_v0(int version, _Unwind_Action actions, #endif // SJ/LJ if (resumeIp == 0) { - return _URC_CONTINUE_UNWIND; + /* No landing pad found, continue unwinding. */ + return continueUnwind(exceptionObject, context); } else { _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), (uintptr_t)exceptionObject); diff --git a/src/compiler-rt/lib/builtins/i386/ashldi3.S b/src/compiler-rt/lib/builtins/i386/ashldi3.S index 3fbd739038..6f05dcf744 100644 --- a/src/compiler-rt/lib/builtins/i386/ashldi3.S +++ b/src/compiler-rt/lib/builtins/i386/ashldi3.S @@ -56,3 +56,6 @@ END_COMPILERRT_FUNCTION(__ashldi3) #endif // __SSE2__ #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/i386/ashrdi3.S b/src/compiler-rt/lib/builtins/i386/ashrdi3.S index 8f4742481b..206369f360 100644 --- a/src/compiler-rt/lib/builtins/i386/ashrdi3.S +++ b/src/compiler-rt/lib/builtins/i386/ashrdi3.S @@ -67,3 +67,6 @@ END_COMPILERRT_FUNCTION(__ashrdi3) #endif // __SSE2__ #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/i386/divdi3.S b/src/compiler-rt/lib/builtins/i386/divdi3.S index 2cb0ddd4c2..2fb4bdcad9 100644 --- a/src/compiler-rt/lib/builtins/i386/divdi3.S +++ b/src/compiler-rt/lib/builtins/i386/divdi3.S @@ -160,3 +160,6 @@ DEFINE_COMPILERRT_FUNCTION(__divdi3) END_COMPILERRT_FUNCTION(__divdi3) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/i386/floatdidf.S b/src/compiler-rt/lib/builtins/i386/floatdidf.S index dcc32f8ed8..d75dfe62d6 100644 --- a/src/compiler-rt/lib/builtins/i386/floatdidf.S +++ b/src/compiler-rt/lib/builtins/i386/floatdidf.S @@ -37,3 +37,6 @@ DEFINE_COMPILERRT_FUNCTION(__floatdidf) END_COMPILERRT_FUNCTION(__floatdidf) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/i386/floatdisf.S b/src/compiler-rt/lib/builtins/i386/floatdisf.S index f642767036..0874eaaa9a 100644 --- a/src/compiler-rt/lib/builtins/i386/floatdisf.S +++ b/src/compiler-rt/lib/builtins/i386/floatdisf.S @@ -30,3 +30,6 @@ DEFINE_COMPILERRT_FUNCTION(__floatdisf) END_COMPILERRT_FUNCTION(__floatdisf) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/i386/floatdixf.S b/src/compiler-rt/lib/builtins/i386/floatdixf.S index 839b0434c0..1044ef55a1 100644 --- a/src/compiler-rt/lib/builtins/i386/floatdixf.S +++ b/src/compiler-rt/lib/builtins/i386/floatdixf.S @@ -28,3 +28,6 @@ DEFINE_COMPILERRT_FUNCTION(__floatdixf) END_COMPILERRT_FUNCTION(__floatdixf) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/i386/floatundidf.S b/src/compiler-rt/lib/builtins/i386/floatundidf.S index 8058c2ac0a..fe032348e8 100644 --- a/src/compiler-rt/lib/builtins/i386/floatundidf.S +++ b/src/compiler-rt/lib/builtins/i386/floatundidf.S @@ -50,3 +50,6 @@ DEFINE_COMPILERRT_FUNCTION(__floatundidf) END_COMPILERRT_FUNCTION(__floatundidf) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/i386/floatundisf.S b/src/compiler-rt/lib/builtins/i386/floatundisf.S index 94c97e25aa..16000b5760 100644 --- a/src/compiler-rt/lib/builtins/i386/floatundisf.S +++ b/src/compiler-rt/lib/builtins/i386/floatundisf.S @@ -103,3 +103,6 @@ DEFINE_COMPILERRT_FUNCTION(__floatundisf) END_COMPILERRT_FUNCTION(__floatundisf) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/i386/floatundixf.S b/src/compiler-rt/lib/builtins/i386/floatundixf.S index 814b52f941..c935670cb5 100644 --- a/src/compiler-rt/lib/builtins/i386/floatundixf.S +++ b/src/compiler-rt/lib/builtins/i386/floatundixf.S @@ -41,3 +41,6 @@ DEFINE_COMPILERRT_FUNCTION(__floatundixf) END_COMPILERRT_FUNCTION(__floatundixf) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/i386/lshrdi3.S b/src/compiler-rt/lib/builtins/i386/lshrdi3.S index b80f11a380..53e95cf765 100644 --- a/src/compiler-rt/lib/builtins/i386/lshrdi3.S +++ b/src/compiler-rt/lib/builtins/i386/lshrdi3.S @@ -57,3 +57,6 @@ END_COMPILERRT_FUNCTION(__lshrdi3) #endif // __SSE2__ #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/i386/moddi3.S b/src/compiler-rt/lib/builtins/i386/moddi3.S index b9cee9d7aa..a5bf9ce8ea 100644 --- a/src/compiler-rt/lib/builtins/i386/moddi3.S +++ b/src/compiler-rt/lib/builtins/i386/moddi3.S @@ -164,3 +164,6 @@ DEFINE_COMPILERRT_FUNCTION(__moddi3) END_COMPILERRT_FUNCTION(__moddi3) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/i386/muldi3.S b/src/compiler-rt/lib/builtins/i386/muldi3.S index 15b6b49984..1239460642 100644 --- a/src/compiler-rt/lib/builtins/i386/muldi3.S +++ b/src/compiler-rt/lib/builtins/i386/muldi3.S @@ -28,3 +28,6 @@ DEFINE_COMPILERRT_FUNCTION(__muldi3) END_COMPILERRT_FUNCTION(__muldi3) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/i386/udivdi3.S b/src/compiler-rt/lib/builtins/i386/udivdi3.S index 41b2edf03e..727613639b 100644 --- a/src/compiler-rt/lib/builtins/i386/udivdi3.S +++ b/src/compiler-rt/lib/builtins/i386/udivdi3.S @@ -113,3 +113,6 @@ DEFINE_COMPILERRT_FUNCTION(__udivdi3) END_COMPILERRT_FUNCTION(__udivdi3) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/i386/umoddi3.S b/src/compiler-rt/lib/builtins/i386/umoddi3.S index a190a7d397..763e821946 100644 --- a/src/compiler-rt/lib/builtins/i386/umoddi3.S +++ b/src/compiler-rt/lib/builtins/i386/umoddi3.S @@ -124,3 +124,6 @@ DEFINE_COMPILERRT_FUNCTION(__umoddi3) END_COMPILERRT_FUNCTION(__umoddi3) #endif // __i386__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/int_endianness.h b/src/compiler-rt/lib/builtins/int_endianness.h index 92511e6a15..7995ddbb95 100644 --- a/src/compiler-rt/lib/builtins/int_endianness.h +++ b/src/compiler-rt/lib/builtins/int_endianness.h @@ -105,19 +105,6 @@ #endif /* Windows */ -#if defined(__linux__) -#include - -#if __BYTE_ORDER == __BIG_ENDIAN -#define _YUGA_LITTLE_ENDIAN 0 -#define _YUGA_BIG_ENDIAN 1 -#elif __BYTE_ORDER == __LITTLE_ENDIAN -#define _YUGA_LITTLE_ENDIAN 1 -#define _YUGA_BIG_ENDIAN 0 -#endif /* __BYTE_ORDER */ - -#endif /* GNU/Linux */ - #endif /* Clang or GCC. */ /* . */ diff --git a/src/compiler-rt/lib/builtins/int_lib.h b/src/compiler-rt/lib/builtins/int_lib.h index 272f9d9dad..e66cda3fff 100644 --- a/src/compiler-rt/lib/builtins/int_lib.h +++ b/src/compiler-rt/lib/builtins/int_lib.h @@ -128,6 +128,6 @@ uint32_t __inline __builtin_clzll(uint64_t value) { #endif #define __builtin_clzl __builtin_clzll -#endif // defined(_MSC_VER) && !defined(__clang__) +#endif /* defined(_MSC_VER) && !defined(__clang__) */ #endif /* INT_LIB_H */ diff --git a/src/compiler-rt/lib/builtins/int_types.h b/src/compiler-rt/lib/builtins/int_types.h index ba1f7522a8..660385ecd6 100644 --- a/src/compiler-rt/lib/builtins/int_types.h +++ b/src/compiler-rt/lib/builtins/int_types.h @@ -20,6 +20,10 @@ #include "int_endianness.h" +/* si_int is defined in Linux sysroot's asm-generic/siginfo.h */ +#ifdef si_int +#undef si_int +#endif typedef int si_int; typedef unsigned su_int; @@ -57,7 +61,8 @@ typedef union } udwords; /* MIPS64 issue: PR 20098 */ -#if defined(__LP64__) && !(defined(__mips__) && defined(__clang__)) +#if (defined(__LP64__) || defined(__wasm__)) && \ + !(defined(__mips__) && defined(__clang__)) #define CRT_HAS_128BIT #endif diff --git a/src/compiler-rt/lib/builtins/ppc/DD.h b/src/compiler-rt/lib/builtins/ppc/DD.h index 679c7f186b..3e5f9e58c1 100644 --- a/src/compiler-rt/lib/builtins/ppc/DD.h +++ b/src/compiler-rt/lib/builtins/ppc/DD.h @@ -1,5 +1,5 @@ -#ifndef __DD_HEADER -#define __DD_HEADER +#ifndef COMPILERRT_DD_HEADER +#define COMPILERRT_DD_HEADER #include "../int_lib.h" @@ -9,7 +9,7 @@ typedef union { double hi; double lo; }s; -}DD; +} DD; typedef union { double d; @@ -37,4 +37,9 @@ static __inline ALWAYS_INLINE int different_sign(double x, double y) { return result; } -#endif /* __DD_HEADER */ +long double __gcc_qadd(long double, long double); +long double __gcc_qsub(long double, long double); +long double __gcc_qmul(long double, long double); +long double __gcc_qdiv(long double, long double); + +#endif /* COMPILERRT_DD_HEADER */ diff --git a/src/compiler-rt/lib/builtins/ppc/divtc3.c b/src/compiler-rt/lib/builtins/ppc/divtc3.c index 2991281863..8ec41c528a 100644 --- a/src/compiler-rt/lib/builtins/ppc/divtc3.c +++ b/src/compiler-rt/lib/builtins/ppc/divtc3.c @@ -14,11 +14,6 @@ (x).s.lo = 0.0; \ } -long double __gcc_qadd(long double, long double); -long double __gcc_qsub(long double, long double); -long double __gcc_qmul(long double, long double); -long double __gcc_qdiv(long double, long double); - long double _Complex __divtc3(long double a, long double b, long double c, long double d) { diff --git a/src/compiler-rt/lib/builtins/ppc/multc3.c b/src/compiler-rt/lib/builtins/ppc/multc3.c index 738b65a83b..9dd79c975d 100644 --- a/src/compiler-rt/lib/builtins/ppc/multc3.c +++ b/src/compiler-rt/lib/builtins/ppc/multc3.c @@ -17,10 +17,6 @@ } \ } -long double __gcc_qadd(long double, long double); -long double __gcc_qsub(long double, long double); -long double __gcc_qmul(long double, long double); - long double _Complex __multc3(long double a, long double b, long double c, long double d) { diff --git a/src/compiler-rt/lib/builtins/ppc/restFP.S b/src/compiler-rt/lib/builtins/ppc/restFP.S index 95032897c0..507e756e18 100644 --- a/src/compiler-rt/lib/builtins/ppc/restFP.S +++ b/src/compiler-rt/lib/builtins/ppc/restFP.S @@ -41,3 +41,6 @@ DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(restFP) lwz r0,8(r1) mtlr r0 blr + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/ppc/saveFP.S b/src/compiler-rt/lib/builtins/ppc/saveFP.S index 72bd459f4c..20b06fff53 100644 --- a/src/compiler-rt/lib/builtins/ppc/saveFP.S +++ b/src/compiler-rt/lib/builtins/ppc/saveFP.S @@ -38,3 +38,6 @@ DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(saveFP) stfd f31,-8(r1) stw r0,8(r1) blr + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/x86_64/floatundidf.S b/src/compiler-rt/lib/builtins/x86_64/floatundidf.S index 3cd5d02a74..094a68dc3c 100644 --- a/src/compiler-rt/lib/builtins/x86_64/floatundidf.S +++ b/src/compiler-rt/lib/builtins/x86_64/floatundidf.S @@ -47,3 +47,6 @@ DEFINE_COMPILERRT_FUNCTION(__floatundidf) END_COMPILERRT_FUNCTION(__floatundidf) #endif // __x86_64__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/x86_64/floatundisf.S b/src/compiler-rt/lib/builtins/x86_64/floatundisf.S index 61952f4047..7c9f75e188 100644 --- a/src/compiler-rt/lib/builtins/x86_64/floatundisf.S +++ b/src/compiler-rt/lib/builtins/x86_64/floatundisf.S @@ -33,3 +33,6 @@ DEFINE_COMPILERRT_FUNCTION(__floatundisf) END_COMPILERRT_FUNCTION(__floatundisf) #endif // __x86_64__ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/builtins/x86_64/floatundixf.S b/src/compiler-rt/lib/builtins/x86_64/floatundixf.S index 92961c8911..28a096b713 100644 --- a/src/compiler-rt/lib/builtins/x86_64/floatundixf.S +++ b/src/compiler-rt/lib/builtins/x86_64/floatundixf.S @@ -66,3 +66,6 @@ END_COMPILERRT_FUNCTION(__floatundixf) #endif // __x86_64__ */ + +NO_EXEC_STACK_DIRECTIVE + diff --git a/src/compiler-rt/lib/cfi/CMakeLists.txt b/src/compiler-rt/lib/cfi/CMakeLists.txt index 90b66a84cc..24e51814cd 100644 --- a/src/compiler-rt/lib/cfi/CMakeLists.txt +++ b/src/compiler-rt/lib/cfi/CMakeLists.txt @@ -1,4 +1,40 @@ add_custom_target(cfi) + +set(CFI_SOURCES cfi.cc) + +include_directories(..) + +set(CFI_CFLAGS + ${SANITIZER_COMMON_CFLAGS} +) + +set(CFI_DIAG_CFLAGS + -DCFI_ENABLE_DIAG=1 +) + +foreach(arch ${CFI_SUPPORTED_ARCH}) + add_compiler_rt_runtime(clang_rt.cfi + STATIC + ARCHS ${arch} + SOURCES ${CFI_SOURCES} + OBJECT_LIBS RTInterception + RTSanitizerCommon + RTSanitizerCommonLibc + CFLAGS ${CFI_CFLAGS} + PARENT_TARGET cfi) + add_compiler_rt_runtime(clang_rt.cfi_diag + STATIC + ARCHS ${arch} + SOURCES ${CFI_SOURCES} + OBJECT_LIBS RTInterception + RTSanitizerCommon + RTSanitizerCommonLibc + RTUbsan + RTUbsan_cxx + CFLAGS ${CFI_CFLAGS} ${CFI_DIAG_CFLAGS} + PARENT_TARGET cfi) +endforeach() + add_compiler_rt_resource_file(cfi_blacklist cfi_blacklist.txt) add_dependencies(cfi cfi_blacklist) add_dependencies(compiler-rt cfi) diff --git a/src/compiler-rt/lib/cfi/cfi.cc b/src/compiler-rt/lib/cfi/cfi.cc new file mode 100644 index 0000000000..711866f3fa --- /dev/null +++ b/src/compiler-rt/lib/cfi/cfi.cc @@ -0,0 +1,271 @@ +//===-------- cfi.cc ------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the runtime support for the cross-DSO CFI. +// +//===----------------------------------------------------------------------===// + +// FIXME: Intercept dlopen/dlclose. +// FIXME: Support diagnostic mode. +// FIXME: Harden: +// * mprotect shadow, use mremap for updates +// * something else equally important + +#include +#include +#include +#include + +typedef ElfW(Phdr) Elf_Phdr; +typedef ElfW(Ehdr) Elf_Ehdr; + +#include "interception/interception.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_flag_parser.h" +#include "ubsan/ubsan_init.h" +#include "ubsan/ubsan_flags.h" + +static uptr __cfi_shadow; +static constexpr uptr kShadowGranularity = 12; +static constexpr uptr kShadowAlign = 1UL << kShadowGranularity; // 4096 + +static constexpr uint16_t kInvalidShadow = 0; +static constexpr uint16_t kUncheckedShadow = 0xFFFFU; + +static uint16_t *mem_to_shadow(uptr x) { + return (uint16_t *)(__cfi_shadow + ((x >> kShadowGranularity) << 1)); +} + +typedef int (*CFICheckFn)(u64, void *); + +class ShadowValue { + uptr addr; + uint16_t v; + explicit ShadowValue(uptr addr, uint16_t v) : addr(addr), v(v) {} + +public: + bool is_invalid() const { return v == kInvalidShadow; } + + bool is_unchecked() const { return v == kUncheckedShadow; } + + CFICheckFn get_cfi_check() const { + assert(!is_invalid() && !is_unchecked()); + uptr aligned_addr = addr & ~(kShadowAlign - 1); + uptr p = aligned_addr - (((uptr)v - 1) << kShadowGranularity); + return reinterpret_cast(p); + } + + // Load a shadow valud for the given application memory address. + static const ShadowValue load(uptr addr) { + return ShadowValue(addr, *mem_to_shadow(addr)); + } +}; + +static void fill_shadow_constant(uptr begin, uptr end, uint16_t v) { + assert(v == kInvalidShadow || v == kUncheckedShadow); + uint16_t *shadow_begin = mem_to_shadow(begin); + uint16_t *shadow_end = mem_to_shadow(end - 1) + 1; + memset(shadow_begin, v, (shadow_end - shadow_begin) * sizeof(*shadow_begin)); +} + +static void fill_shadow(uptr begin, uptr end, uptr cfi_check) { + assert((cfi_check & (kShadowAlign - 1)) == 0); + + // Don't fill anything below cfi_check. We can not represent those addresses + // in the shadow, and must make sure at codegen to place all valid call + // targets above cfi_check. + uptr p = Max(begin, cfi_check); + uint16_t *s = mem_to_shadow(p); + uint16_t *s_end = mem_to_shadow(end - 1) + 1; + uint16_t sv = ((p - cfi_check) >> kShadowGranularity) + 1; + for (; s < s_end; s++, sv++) + *s = sv; + + // Sanity checks. + uptr q = p & ~(kShadowAlign - 1); + for (; q < end; q += kShadowAlign) { + assert((uptr)ShadowValue::load(q).get_cfi_check() == cfi_check); + assert((uptr)ShadowValue::load(q + kShadowAlign / 2).get_cfi_check() == + cfi_check); + assert((uptr)ShadowValue::load(q + kShadowAlign - 1).get_cfi_check() == + cfi_check); + } +} + +// This is a workaround for a glibc bug: +// https://sourceware.org/bugzilla/show_bug.cgi?id=15199 +// Other platforms can, hopefully, just do +// dlopen(RTLD_NOLOAD | RTLD_LAZY) +// dlsym("__cfi_check"). +static uptr find_cfi_check_in_dso(dl_phdr_info *info) { + const ElfW(Dyn) *dynamic = nullptr; + for (int i = 0; i < info->dlpi_phnum; ++i) { + if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) { + dynamic = + (const ElfW(Dyn) *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr); + break; + } + } + if (!dynamic) return 0; + uptr strtab = 0, symtab = 0; + for (const ElfW(Dyn) *p = dynamic; p->d_tag != PT_NULL; ++p) { + if (p->d_tag == DT_SYMTAB) + symtab = p->d_un.d_ptr; + else if (p->d_tag == DT_STRTAB) + strtab = p->d_un.d_ptr; + } + + if (symtab > strtab) { + VReport(1, "Can not handle: symtab > strtab (%p > %zx)\n", symtab, strtab); + return 0; + } + + // Verify that strtab and symtab are inside of the same LOAD segment. + // This excludes VDSO, which has (very high) bogus strtab and symtab pointers. + int phdr_idx; + for (phdr_idx = 0; phdr_idx < info->dlpi_phnum; phdr_idx++) { + const Elf_Phdr *phdr = &info->dlpi_phdr[phdr_idx]; + if (phdr->p_type == PT_LOAD) { + uptr beg = info->dlpi_addr + phdr->p_vaddr; + uptr end = beg + phdr->p_memsz; + if (strtab >= beg && strtab < end && symtab >= beg && symtab < end) + break; + } + } + if (phdr_idx == info->dlpi_phnum) { + // Nope, either different segments or just bogus pointers. + // Can not handle this. + VReport(1, "Can not handle: symtab %p, strtab %zx\n", symtab, strtab); + return 0; + } + + for (const ElfW(Sym) *p = (const ElfW(Sym) *)symtab; (ElfW(Addr))p < strtab; + ++p) { + char *name = (char*)(strtab + p->st_name); + if (strcmp(name, "__cfi_check") == 0) { + assert(p->st_info == ELF32_ST_INFO(STB_GLOBAL, STT_FUNC)); + uptr addr = info->dlpi_addr + p->st_value; + return addr; + } + } + return 0; +} + +static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *data) { + uptr cfi_check = find_cfi_check_in_dso(info); + if (cfi_check) + VReport(1, "Module '%s' __cfi_check %zx\n", info->dlpi_name, cfi_check); + + for (int i = 0; i < info->dlpi_phnum; i++) { + const Elf_Phdr *phdr = &info->dlpi_phdr[i]; + if (phdr->p_type == PT_LOAD) { + // Jump tables are in the executable segment. + // VTables are in the non-executable one. + // Need to fill shadow for both. + // FIXME: reject writable if vtables are in the r/o segment. Depend on + // PT_RELRO? + uptr cur_beg = info->dlpi_addr + phdr->p_vaddr; + uptr cur_end = cur_beg + phdr->p_memsz; + if (cfi_check) { + VReport(1, " %zx .. %zx\n", cur_beg, cur_end); + fill_shadow(cur_beg, cur_end, cfi_check ? cfi_check : (uptr)(-1)); + } else { + fill_shadow_constant(cur_beg, cur_end, kUncheckedShadow); + } + } + } + return 0; +} + +// Fill shadow for the initial libraries. +static void init_shadow() { + dl_iterate_phdr(dl_iterate_phdr_cb, nullptr); +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void __cfi_slowpath(u64 CallSiteTypeId, void *Ptr) { + uptr Addr = (uptr)Ptr; + VReport(3, "__cfi_slowpath: %llx, %p\n", CallSiteTypeId, Ptr); + ShadowValue sv = ShadowValue::load(Addr); + if (sv.is_invalid()) { + VReport(2, "CFI: invalid memory region for a function pointer (shadow==0): %p\n", Ptr); + Die(); + } + if (sv.is_unchecked()) { + VReport(2, "CFI: unchecked call (shadow=FFFF): %p\n", Ptr); + return; + } + CFICheckFn cfi_check = sv.get_cfi_check(); + VReport(2, "__cfi_check at %p\n", cfi_check); + cfi_check(CallSiteTypeId, Ptr); +} + +static void InitializeFlags() { + SetCommonFlagsDefaults(); +#ifdef CFI_ENABLE_DIAG + __ubsan::Flags *uf = __ubsan::flags(); + uf->SetDefaults(); +#endif + + FlagParser cfi_parser; + RegisterCommonFlags(&cfi_parser); + cfi_parser.ParseString(GetEnv("CFI_OPTIONS")); + +#ifdef CFI_ENABLE_DIAG + FlagParser ubsan_parser; + __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); + RegisterCommonFlags(&ubsan_parser); + + const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions(); + ubsan_parser.ParseString(ubsan_default_options); + ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS")); +#endif + + SetVerbosity(common_flags()->verbosity); + + if (Verbosity()) ReportUnrecognizedFlags(); + + if (common_flags()->help) { + cfi_parser.PrintFlagDescriptions(); + } +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +#if !SANITIZER_CAN_USE_PREINIT_ARRAY +// On ELF platforms, the constructor is invoked using .preinit_array (see below) +__attribute__((constructor(0))) +#endif +void __cfi_init() { + SanitizerToolName = "CFI"; + InitializeFlags(); + + uptr vma = GetMaxVirtualAddress(); + // Shadow is 2 -> 2**kShadowGranularity. + uptr shadow_size = (vma >> (kShadowGranularity - 1)) + 1; + VReport(1, "CFI: VMA size %zx, shadow size %zx\n", vma, shadow_size); + void *shadow = MmapNoReserveOrDie(shadow_size, "CFI shadow"); + VReport(1, "CFI: shadow at %zx .. %zx\n", shadow, + reinterpret_cast(shadow) + shadow_size); + __cfi_shadow = (uptr)shadow; + init_shadow(); + +#ifdef CFI_ENABLE_DIAG + __ubsan::InitAsPlugin(); +#endif +} + +#if SANITIZER_CAN_USE_PREINIT_ARRAY +// On ELF platforms, run cfi initialization before any other constructors. +// On other platforms we use the constructor attribute to arrange to run our +// initialization early. +extern "C" { +__attribute__((section(".preinit_array"), + used)) void (*__cfi_preinit)(void) = __cfi_init; +} +#endif diff --git a/src/compiler-rt/lib/dfsan/.clang-format b/src/compiler-rt/lib/dfsan/.clang-format new file mode 100644 index 0000000000..f6cb8ad931 --- /dev/null +++ b/src/compiler-rt/lib/dfsan/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: Google diff --git a/src/compiler-rt/lib/dfsan/dfsan.cc b/src/compiler-rt/lib/dfsan/dfsan.cc index f4bef921a3..7285f202d0 100644 --- a/src/compiler-rt/lib/dfsan/dfsan.cc +++ b/src/compiler-rt/lib/dfsan/dfsan.cc @@ -42,6 +42,8 @@ Flags __dfsan::flags_data; SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL dfsan_label __dfsan_retval_tls; SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL dfsan_label __dfsan_arg_tls[64]; +SANITIZER_INTERFACE_ATTRIBUTE uptr __dfsan_shadow_ptr_mask; + // On Linux/x86_64, memory is laid out as follows: // // +--------------------+ 0x800000000000 (top of memory) @@ -114,35 +116,18 @@ SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL dfsan_label __dfsan_arg_tls[64]; typedef atomic_dfsan_label dfsan_union_table_t[kNumLabels][kNumLabels]; -#if defined(__x86_64__) -static const uptr kShadowAddr = 0x10000; -static const uptr kUnionTableAddr = 0x200000000000; -static const uptr kUnusedAddr = kUnionTableAddr + sizeof(dfsan_union_table_t); -static const uptr kAppAddr = 0x700000008000; -#elif defined(__mips64) -static const uptr kShadowAddr = 0x10000; -static const uptr kUnionTableAddr = 0x2000000000; -static const uptr kUnusedAddr = kUnionTableAddr + sizeof(dfsan_union_table_t); -static const uptr kAppAddr = 0xF000008000; -#elif defined(__aarch64__) -static const uptr kShadowAddr = 0x10000; -# if SANITIZER_AARCH64_VMA == 39 -static const uptr kUnionTableAddr = 0x1000000000; -# elif SANITIZER_AARCH64_VMA == 42 -static const uptr kUnionTableAddr = 0x8000000000; -# endif -static const uptr kUnusedAddr = kUnionTableAddr + sizeof(dfsan_union_table_t); -# if SANITIZER_AARCH64_VMA == 39 -static const uptr kAppAddr = 0x7000008000; -# elif SANITIZER_AARCH64_VMA == 42 -static const uptr kAppAddr = 0x3ff00008000; -# endif -#else -# error "DFSan not supported for this platform!" +#ifdef DFSAN_RUNTIME_VMA +// Runtime detected VMA size. +int __dfsan::vmaSize; #endif +static uptr UnusedAddr() { + return MappingArchImpl() + + sizeof(dfsan_union_table_t); +} + static atomic_dfsan_label *union_table(dfsan_label l1, dfsan_label l2) { - return &(*(dfsan_union_table_t *) kUnionTableAddr)[l1][l2]; + return &(*(dfsan_union_table_t *) UnionTableAddr())[l1][l2]; } // Checks we do not run out of labels. @@ -382,6 +367,20 @@ static void InitializeFlags() { if (common_flags()->help) parser.PrintFlagDescriptions(); } +static void InitializePlatformEarly() { +#ifdef DFSAN_RUNTIME_VMA + __dfsan::vmaSize = + (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); + if (__dfsan::vmaSize == 39 || __dfsan::vmaSize == 42) { + __dfsan_shadow_ptr_mask = ShadowMask(); + } else { + Printf("FATAL: DataFlowSanitizer: unsupported VMA range\n"); + Printf("FATAL: Found %d - Supported 39 and 42\n", __dfsan::vmaSize); + Die(); + } +#endif +} + static void dfsan_fini() { if (internal_strcmp(flags().dump_labels_at_exit, "") != 0) { fd_t fd = OpenFile(flags().dump_labels_at_exit, WrOnly); @@ -401,9 +400,9 @@ static void dfsan_fini() { static void dfsan_init(int argc, char **argv, char **envp) { InitializeFlags(); - CheckVMASize(); + InitializePlatformEarly(); - MmapFixedNoReserve(kShadowAddr, kUnusedAddr - kShadowAddr); + MmapFixedNoReserve(ShadowAddr(), UnusedAddr() - ShadowAddr()); // Protect the region of memory we don't use, to preserve the one-to-one // mapping from application to shadow memory. But if ASLR is disabled, Linux @@ -411,8 +410,8 @@ static void dfsan_init(int argc, char **argv, char **envp) { // works so long as the program doesn't use too much memory. We support this // case by disabling memory protection when ASLR is disabled. uptr init_addr = (uptr)&dfsan_init; - if (!(init_addr >= kUnusedAddr && init_addr < kAppAddr)) - MmapNoAccess(kUnusedAddr, kAppAddr - kUnusedAddr); + if (!(init_addr >= UnusedAddr() && init_addr < AppAddr())) + MmapNoAccess(UnusedAddr(), AppAddr() - UnusedAddr()); InitializeInterceptors(); diff --git a/src/compiler-rt/lib/dfsan/dfsan.h b/src/compiler-rt/lib/dfsan/dfsan.h index df222e49bb..81f949e301 100644 --- a/src/compiler-rt/lib/dfsan/dfsan.h +++ b/src/compiler-rt/lib/dfsan/dfsan.h @@ -16,6 +16,7 @@ #define DFSAN_H #include "sanitizer_common/sanitizer_internal_defs.h" +#include "dfsan_platform.h" // Copy declarations from public sanitizer/dfsan_interface.h header here. typedef u16 dfsan_label; @@ -44,17 +45,7 @@ namespace __dfsan { void InitializeInterceptors(); inline dfsan_label *shadow_for(void *ptr) { -#if defined(__x86_64__) - return (dfsan_label *) ((((uptr) ptr) & ~0x700000000000) << 1); -#elif defined(__mips64) - return (dfsan_label *) ((((uptr) ptr) & ~0xF000000000) << 1); -#elif defined(__aarch64__) -# if SANITIZER_AARCH64_VMA == 39 - return (dfsan_label *) ((((uptr) ptr) & ~0x7800000000) << 1); -# elif SANITIZER_AARCH64_VMA == 42 - return (dfsan_label *) ((((uptr) ptr) & ~0x3c000000000) << 1); -# endif -#endif + return (dfsan_label *) ((((uptr) ptr) & ShadowMask()) << 1); } inline const dfsan_label *shadow_for(const void *ptr) { diff --git a/src/compiler-rt/lib/dfsan/dfsan_platform.h b/src/compiler-rt/lib/dfsan/dfsan_platform.h new file mode 100644 index 0000000000..f1d9f108e9 --- /dev/null +++ b/src/compiler-rt/lib/dfsan/dfsan_platform.h @@ -0,0 +1,107 @@ +//===-- dfsan_platform.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 a part of DataFlowSanitizer. +// +// Platform specific information for DFSan. +//===----------------------------------------------------------------------===// + +#ifndef DFSAN_PLATFORM_H +#define DFSAN_PLATFORM_H + +namespace __dfsan { + +#if defined(__x86_64__) +struct Mapping { + static const uptr kShadowAddr = 0x10000; + static const uptr kUnionTableAddr = 0x200000000000; + static const uptr kAppAddr = 0x700000008000; + static const uptr kShadowMask = ~0x700000000000; +}; +#elif defined(__mips64) +struct Mapping { + static const uptr kShadowAddr = 0x10000; + static const uptr kUnionTableAddr = 0x2000000000; + static const uptr kAppAddr = 0xF000008000; + static const uptr kShadowMask = ~0xF000000000; +}; +#elif defined(__aarch64__) +struct Mapping39 { + static const uptr kShadowAddr = 0x10000; + static const uptr kUnionTableAddr = 0x1000000000; + static const uptr kAppAddr = 0x7000008000; + static const uptr kShadowMask = ~0x7800000000; +}; + +struct Mapping42 { + static const uptr kShadowAddr = 0x10000; + static const uptr kUnionTableAddr = 0x8000000000; + static const uptr kAppAddr = 0x3ff00008000; + static const uptr kShadowMask = ~0x3c000000000; +}; + +extern int vmaSize; +# define DFSAN_RUNTIME_VMA 1 +#else +# error "DFSan not supported for this platform!" +#endif + +enum MappingType { + MAPPING_SHADOW_ADDR, + MAPPING_UNION_TABLE_ADDR, + MAPPING_APP_ADDR, + MAPPING_SHADOW_MASK +}; + +template +uptr MappingImpl(void) { + switch (Type) { + case MAPPING_SHADOW_ADDR: return Mapping::kShadowAddr; + case MAPPING_UNION_TABLE_ADDR: return Mapping::kUnionTableAddr; + case MAPPING_APP_ADDR: return Mapping::kAppAddr; + case MAPPING_SHADOW_MASK: return Mapping::kShadowMask; + } +} + +template +uptr MappingArchImpl(void) { +#ifdef __aarch64__ + if (vmaSize == 39) + return MappingImpl(); + else + return MappingImpl(); + DCHECK(0); +#else + return MappingImpl(); +#endif +} + +ALWAYS_INLINE +uptr ShadowAddr() { + return MappingArchImpl(); +} + +ALWAYS_INLINE +uptr UnionTableAddr() { + return MappingArchImpl(); +} + +ALWAYS_INLINE +uptr AppAddr() { + return MappingArchImpl(); +} + +ALWAYS_INLINE +uptr ShadowMask() { + return MappingArchImpl(); +} + +} // namespace __dfsan + +#endif diff --git a/src/compiler-rt/lib/interception/.clang-format b/src/compiler-rt/lib/interception/.clang-format new file mode 100644 index 0000000000..f6cb8ad931 --- /dev/null +++ b/src/compiler-rt/lib/interception/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: Google diff --git a/src/compiler-rt/lib/lsan/.clang-format b/src/compiler-rt/lib/lsan/.clang-format new file mode 100644 index 0000000000..f6cb8ad931 --- /dev/null +++ b/src/compiler-rt/lib/lsan/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: Google diff --git a/src/compiler-rt/lib/lsan/lsan_common.cc b/src/compiler-rt/lib/lsan/lsan_common.cc index 6600abb9a1..1cffac4439 100644 --- a/src/compiler-rt/lib/lsan/lsan_common.cc +++ b/src/compiler-rt/lib/lsan/lsan_common.cc @@ -120,7 +120,9 @@ static inline bool CanBeAHeapPointer(uptr p) { #elif defined(__mips64) return ((p >> 40) == 0); #elif defined(__aarch64__) - return ((p >> SANITIZER_AARCH64_VMA) == 0); + unsigned runtimeVMA = + (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); + return ((p >> runtimeVMA) == 0); #else return true; #endif diff --git a/src/compiler-rt/lib/msan/.clang-format b/src/compiler-rt/lib/msan/.clang-format new file mode 100644 index 0000000000..f6cb8ad931 --- /dev/null +++ b/src/compiler-rt/lib/msan/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: Google diff --git a/src/compiler-rt/lib/msan/msan.cc b/src/compiler-rt/lib/msan/msan.cc index b64dcb6ffe..9949db4c13 100644 --- a/src/compiler-rt/lib/msan/msan.cc +++ b/src/compiler-rt/lib/msan/msan.cc @@ -55,7 +55,7 @@ SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u32 __msan_retval_origin_tls; SANITIZER_INTERFACE_ATTRIBUTE -THREADLOCAL u64 __msan_va_arg_tls[kMsanParamTlsSize / sizeof(u64)]; +ALIGNED(16) THREADLOCAL u64 __msan_va_arg_tls[kMsanParamTlsSize / sizeof(u64)]; SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u64 __msan_va_arg_overflow_size_tls; diff --git a/src/compiler-rt/lib/msan/msan_interceptors.cc b/src/compiler-rt/lib/msan/msan_interceptors.cc index 1bf196ecdb..0db2ac5b22 100644 --- a/src/compiler-rt/lib/msan/msan_interceptors.cc +++ b/src/compiler-rt/lib/msan/msan_interceptors.cc @@ -1408,12 +1408,12 @@ int OnExit() { __msan_unpoison(ptr, size) #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ if (msan_init_is_running) return REAL(func)(__VA_ARGS__); \ + ENSURE_MSAN_INITED(); \ MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \ ctx = (void *)&msan_ctx; \ (void)ctx; \ InterceptorScope interceptor_scope; \ - __msan_unpoison(__errno_location(), sizeof(int)); /* NOLINT */ \ - ENSURE_MSAN_INITED(); + __msan_unpoison(__errno_location(), sizeof(int)); /* NOLINT */ #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \ do { \ } while (false) @@ -1434,10 +1434,11 @@ int OnExit() { } while (false) // FIXME #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() -#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \ - do { \ - link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle)); \ - if (map) ForEachMappedRegion(map, __msan_unpoison); \ +#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \ + do { \ + link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle)); \ + if (filename && map) \ + ForEachMappedRegion(map, __msan_unpoison); \ } while (false) #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ diff --git a/src/compiler-rt/lib/msan/tests/msan_test.cc b/src/compiler-rt/lib/msan/tests/msan_test.cc index 57938329d2..b7162b3c08 100644 --- a/src/compiler-rt/lib/msan/tests/msan_test.cc +++ b/src/compiler-rt/lib/msan/tests/msan_test.cc @@ -1883,7 +1883,7 @@ TEST(MemorySanitizer, swprintf) { ASSERT_EQ(buff[1], '2'); ASSERT_EQ(buff[2], '3'); ASSERT_EQ(buff[6], '7'); - ASSERT_EQ(buff[7], 0); + ASSERT_EQ(buff[7], L'\0'); EXPECT_POISONED(buff[8]); } @@ -2886,6 +2886,8 @@ static void GetPathToLoadable(char *buf, size_t sz) { static const char basename[] = "libmsan_loadable.mips64.so"; #elif defined(__mips64) static const char basename[] = "libmsan_loadable.mips64el.so"; +#elif defined(__aarch64__) + static const char basename[] = "libmsan_loadable.aarch64.so"; #endif int res = snprintf(buf, sz, "%.*s/%s", (int)dir_len, program_path, basename); @@ -2992,6 +2994,14 @@ static void *SmallStackThread_threadfn(void* data) { return 0; } +#ifdef PTHREAD_STACK_MIN +# define SMALLSTACKSIZE PTHREAD_STACK_MIN +# define SMALLPRESTACKSIZE PTHREAD_STACK_MIN +#else +# define SMALLSTACKSIZE 64 * 1024 +# define SMALLPRESTACKSIZE 16 * 1024 +#endif + TEST(MemorySanitizer, SmallStackThread) { pthread_attr_t attr; pthread_t t; @@ -2999,7 +3009,7 @@ TEST(MemorySanitizer, SmallStackThread) { int res; res = pthread_attr_init(&attr); ASSERT_EQ(0, res); - res = pthread_attr_setstacksize(&attr, 64 * 1024); + res = pthread_attr_setstacksize(&attr, SMALLSTACKSIZE); ASSERT_EQ(0, res); res = pthread_create(&t, &attr, SmallStackThread_threadfn, NULL); ASSERT_EQ(0, res); @@ -3016,7 +3026,7 @@ TEST(MemorySanitizer, SmallPreAllocatedStackThread) { res = pthread_attr_init(&attr); ASSERT_EQ(0, res); void *stack; - const size_t kStackSize = 16 * 1024; + const size_t kStackSize = SMALLPRESTACKSIZE; res = posix_memalign(&stack, 4096, kStackSize); ASSERT_EQ(0, res); res = pthread_attr_setstack(&attr, stack, kStackSize); diff --git a/src/compiler-rt/lib/profile/CMakeLists.txt b/src/compiler-rt/lib/profile/CMakeLists.txt index 6b37b39b4f..17eb48a5b2 100644 --- a/src/compiler-rt/lib/profile/CMakeLists.txt +++ b/src/compiler-rt/lib/profile/CMakeLists.txt @@ -1,16 +1,58 @@ + +CHECK_CXX_SOURCE_COMPILES(" +#ifdef _MSC_VER +#include /* Workaround for PR19898. */ +#include +#endif +int main() { +#ifdef _MSC_VER + volatile LONG val = 1; + MemoryBarrier(); + InterlockedCompareExchange(&val, 0, 1); + InterlockedIncrement(&val); + InterlockedDecrement(&val); +#else + volatile unsigned long val = 1; + __sync_synchronize(); + __sync_val_compare_and_swap(&val, 1, 0); + __sync_add_and_fetch(&val, 1); + __sync_sub_and_fetch(&val, 1); +#endif + return 0; + } +" COMPILER_RT_TARGET_HAS_ATOMICS) + add_custom_target(profile) set(PROFILE_SOURCES GCDAProfiling.c InstrProfiling.c + InstrProfilingValue.c InstrProfilingBuffer.c InstrProfilingFile.c + InstrProfilingWriter.c InstrProfilingPlatformDarwin.c InstrProfilingPlatformLinux.c InstrProfilingPlatformOther.c InstrProfilingRuntime.cc InstrProfilingUtil.c) +if(WIN32) + list(APPEND PROFILE_SOURCES WindowsMMap.c) +endif() + +if(UNIX) + set(EXTRA_FLAGS + -fPIC + -Wno-pedantic) +endif() + +if(COMPILER_RT_TARGET_HAS_ATOMICS) + set(EXTRA_FLAGS + ${EXTRA_FLAGS} + -DCOMPILER_RT_HAS_ATOMICS=1) +endif() + if(APPLE) add_compiler_rt_runtime(clang_rt.profile STATIC @@ -22,7 +64,7 @@ else() add_compiler_rt_runtime(clang_rt.profile STATIC ARCHS ${PROFILE_SUPPORTED_ARCH} - CFLAGS -fPIC + CFLAGS ${EXTRA_FLAGS} SOURCES ${PROFILE_SOURCES} PARENT_TARGET profile) endif() diff --git a/src/compiler-rt/lib/profile/GCDAProfiling.c b/src/compiler-rt/lib/profile/GCDAProfiling.c index aec232856e..2338761ae1 100644 --- a/src/compiler-rt/lib/profile/GCDAProfiling.c +++ b/src/compiler-rt/lib/profile/GCDAProfiling.c @@ -27,8 +27,13 @@ #include #include #include + +#if defined(_WIN32) +#include "WindowsMMap.h" +#else #include #include +#endif #define I386_FREEBSD (defined(__FreeBSD__) && defined(__i386__)) @@ -37,6 +42,7 @@ #endif #if defined(_MSC_VER) +typedef unsigned char uint8_t; typedef unsigned int uint32_t; typedef unsigned long long uint64_t; #elif I386_FREEBSD diff --git a/src/compiler-rt/lib/profile/InstrProfData.inc b/src/compiler-rt/lib/profile/InstrProfData.inc new file mode 100644 index 0000000000..33c7d94aea --- /dev/null +++ b/src/compiler-rt/lib/profile/InstrProfData.inc @@ -0,0 +1,767 @@ +/*===-- InstrProfData.inc - instr profiling runtime structures -*- C++ -*-=== *\ +|* +|* The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +\*===----------------------------------------------------------------------===*/ +/* + * This is the master file that defines all the data structure, signature, + * constant literals that are shared across profiling runtime library, + * compiler (instrumentation), and host tools (reader/writer). The entities + * defined in this file affect the profile runtime ABI, the raw profile format, + * or both. + * + * The file has two identical copies. The master copy lives in LLVM and + * the other one sits in compiler-rt/lib/profile directory. To make changes + * in this file, first modify the master copy and copy it over to compiler-rt. + * Testing of any change in this file can start only after the two copies are + * synced up. + * + * The first part of the file includes macros that defines types, names, and + * initializers for the member fields of the core data structures. The field + * declarations for one structure is enabled by defining the field activation + * macro associated with that structure. Only one field activation record + * can be defined at one time and the rest definitions will be filtered out by + * the preprocessor. + * + * Examples of how the template is used to instantiate structure definition: + * 1. To declare a structure: + * + * struct ProfData { + * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \ + * Type Name; + * #include "llvm/ProfileData/InstrProfData.inc" + * }; + * + * 2. To construct LLVM type arrays for the struct type: + * + * Type *DataTypes[] = { + * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \ + * LLVMType, + * #include "llvm/ProfileData/InstrProfData.inc" + * }; + * + * 4. To construct constant array for the initializers: + * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \ + * Initializer, + * Constant *ConstantVals[] = { + * #include "llvm/ProfileData/InstrProfData.inc" + * }; + * + * + * The second part of the file includes definitions all other entities that + * are related to runtime ABI and format. When no field activation macro is + * defined, this file can be included to introduce the definitions. + * +\*===----------------------------------------------------------------------===*/ + +/* INSTR_PROF_DATA start. */ +/* Definition of member fields of the per-function control structure. */ +#ifndef INSTR_PROF_DATA +#define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) +#else +#define INSTR_PROF_DATA_DEFINED +#endif + +INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NameSize, \ + ConstantInt::get(llvm::Type::getInt32Ty(Ctx), \ + NamePtr->getType()->getPointerElementType()->getArrayNumElements())) +INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumCounters, \ + ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumCounters)) +INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \ + ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \ + Inc->getHash()->getZExtValue())) +INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), NamePtr, \ + ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx))) +INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt64PtrTy(Ctx), CounterPtr, \ + ConstantExpr::getBitCast(CounterPtr, \ + llvm::Type::getInt64PtrTy(Ctx))) +INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), FunctionPointer, \ + FunctionAddr) +INSTR_PROF_DATA(IntPtrT, llvm::Type::getInt8PtrTy(Ctx), Values, \ + ConstantPointerNull::get(Int8PtrTy)) +INSTR_PROF_DATA(const uint16_t, Int16ArrayTy, NumValueSites[IPVK_Last+1], \ + ConstantArray::get(Int16ArrayTy, Int16ArrayVals)) +#undef INSTR_PROF_DATA +/* INSTR_PROF_DATA end. */ + +/* INSTR_PROF_RAW_HEADER start */ +/* Definition of member fields of the raw profile header data structure. */ +#ifndef INSTR_PROF_RAW_HEADER +#define INSTR_PROF_RAW_HEADER(Type, Name, Initializer) +#else +#define INSTR_PROF_DATA_DEFINED +#endif +INSTR_PROF_RAW_HEADER(uint64_t, Magic, __llvm_profile_get_magic()) +INSTR_PROF_RAW_HEADER(uint64_t, Version, __llvm_profile_get_version()) +INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize) +INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize) +INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize) +INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin) +INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin) +INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last) +INSTR_PROF_RAW_HEADER(uint64_t, ValueDataSize, ValueDataSize) +INSTR_PROF_RAW_HEADER(uint64_t, ValueDataDelta, (uintptr_t)ValueDataBegin) +#undef INSTR_PROF_RAW_HEADER +/* INSTR_PROF_RAW_HEADER end */ + +/* VALUE_PROF_FUNC_PARAM start */ +/* Definition of parameter types of the runtime API used to do value profiling + * for a given value site. + */ +#ifndef VALUE_PROF_FUNC_PARAM +#define VALUE_PROF_FUNC_PARAM(ArgType, ArgName, ArgLLVMType) +#define INSTR_PROF_COMMA +#else +#define INSTR_PROF_DATA_DEFINED +#define INSTR_PROF_COMMA , +#endif +VALUE_PROF_FUNC_PARAM(uint64_t, TargetValue, Type::getInt64Ty(Ctx)) \ + INSTR_PROF_COMMA +VALUE_PROF_FUNC_PARAM(void *, Data, Type::getInt8PtrTy(Ctx)) INSTR_PROF_COMMA +VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx)) +#undef VALUE_PROF_FUNC_PARAM +#undef INSTR_PROF_COMMA +/* VALUE_PROF_FUNC_PARAM end */ + +/* VALUE_PROF_KIND start */ +#ifndef VALUE_PROF_KIND +#define VALUE_PROF_KIND(Enumerator, Value) +#else +#define INSTR_PROF_DATA_DEFINED +#endif +VALUE_PROF_KIND(IPVK_IndirectCallTarget, 0) +/* These two kinds must be the last to be + * declared. This is to make sure the string + * array created with the template can be + * indexed with the kind value. + */ +VALUE_PROF_KIND(IPVK_First, IPVK_IndirectCallTarget) +VALUE_PROF_KIND(IPVK_Last, IPVK_IndirectCallTarget) + +#undef VALUE_PROF_KIND +/* VALUE_PROF_KIND end */ + +/* COVMAP_FUNC_RECORD start */ +/* Definition of member fields of the function record structure in coverage + * map. + */ +#ifndef COVMAP_FUNC_RECORD +#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Initializer) +#else +#define INSTR_PROF_DATA_DEFINED +#endif +COVMAP_FUNC_RECORD(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), \ + NamePtr, llvm::ConstantExpr::getBitCast(NamePtr, \ + llvm::Type::getInt8PtrTy(Ctx))) +COVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), NameSize, \ + llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx),\ + NameValue.size())) +COVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), DataSize, \ + llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx),\ + CoverageMapping.size())) +COVMAP_FUNC_RECORD(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \ + llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), FuncHash)) +#undef COVMAP_FUNC_RECORD +/* COVMAP_FUNC_RECORD end. */ + +/* COVMAP_HEADER start */ +/* Definition of member fields of coverage map header. + */ +#ifndef COVMAP_HEADER +#define COVMAP_HEADER(Type, LLVMType, Name, Initializer) +#else +#define INSTR_PROF_DATA_DEFINED +#endif +COVMAP_HEADER(uint32_t, Int32Ty, NRecords, \ + llvm::ConstantInt::get(Int32Ty, FunctionRecords.size())) +COVMAP_HEADER(uint32_t, Int32Ty, FilenamesSize, \ + llvm::ConstantInt::get(Int32Ty, FilenamesSize)) +COVMAP_HEADER(uint32_t, Int32Ty, CoverageSize, \ + llvm::ConstantInt::get(Int32Ty, CoverageMappingSize)) +COVMAP_HEADER(uint32_t, Int32Ty, Version, \ + llvm::ConstantInt::get(Int32Ty, CoverageMappingCurrentVersion)) +#undef COVMAP_HEADER +/* COVMAP_HEADER end. */ + + +#ifdef INSTR_PROF_VALUE_PROF_DATA +#define INSTR_PROF_DATA_DEFINED + +#define INSTR_PROF_MAX_NUM_VAL_PER_SITE 255 +/*! + * This is the header of the data structure that defines the on-disk + * layout of the value profile data of a particular kind for one function. + */ +typedef struct ValueProfRecord { + /* The kind of the value profile record. */ + uint32_t Kind; + /* + * The number of value profile sites. It is guaranteed to be non-zero; + * otherwise the record for this kind won't be emitted. + */ + uint32_t NumValueSites; + /* + * The first element of the array that stores the number of profiled + * values for each value site. The size of the array is NumValueSites. + * Since NumValueSites is greater than zero, there is at least one + * element in the array. + */ + uint8_t SiteCountArray[1]; + + /* + * The fake declaration is for documentation purpose only. + * Align the start of next field to be on 8 byte boundaries. + uint8_t Padding[X]; + */ + + /* The array of value profile data. The size of the array is the sum + * of all elements in SiteCountArray[]. + InstrProfValueData ValueData[]; + */ + +#ifdef __cplusplus + /*! + * \brief Return the number of value sites. + */ + uint32_t getNumValueSites() const { return NumValueSites; } + /*! + * \brief Read data from this record and save it to Record. + */ + void deserializeTo(InstrProfRecord &Record, + InstrProfRecord::ValueMapType *VMap); + /* + * In-place byte swap: + * Do byte swap for this instance. \c Old is the original order before + * the swap, and \c New is the New byte order. + */ + void swapBytes(support::endianness Old, support::endianness New); +#endif +} ValueProfRecord; + +/*! + * Per-function header/control data structure for value profiling + * data in indexed format. + */ +typedef struct ValueProfData { + /* + * Total size in bytes including this field. It must be a multiple + * of sizeof(uint64_t). + */ + uint32_t TotalSize; + /* + *The number of value profile kinds that has value profile data. + * In this implementation, a value profile kind is considered to + * have profile data if the number of value profile sites for the + * kind is not zero. More aggressively, the implementation can + * choose to check the actual data value: if none of the value sites + * has any profiled values, the kind can be skipped. + */ + uint32_t NumValueKinds; + + /* + * Following are a sequence of variable length records. The prefix/header + * of each record is defined by ValueProfRecord type. The number of + * records is NumValueKinds. + * ValueProfRecord Record_1; + * ValueProfRecord Record_N; + */ + +#if __cplusplus + /*! + * Return the total size in bytes of the on-disk value profile data + * given the data stored in Record. + */ + static uint32_t getSize(const InstrProfRecord &Record); + /*! + * Return a pointer to \c ValueProfData instance ready to be streamed. + */ + static std::unique_ptr + serializeFrom(const InstrProfRecord &Record); + /*! + * Check the integrity of the record. Return the error code when + * an error is detected, otherwise return instrprof_error::success. + */ + instrprof_error checkIntegrity(); + /*! + * Return a pointer to \c ValueProfileData instance ready to be read. + * All data in the instance are properly byte swapped. The input + * data is assumed to be in little endian order. + */ + static ErrorOr> + getValueProfData(const unsigned char *SrcBuffer, + const unsigned char *const SrcBufferEnd, + support::endianness SrcDataEndianness); + /*! + * Swap byte order from \c Endianness order to host byte order. + */ + void swapBytesToHost(support::endianness Endianness); + /*! + * Swap byte order from host byte order to \c Endianness order. + */ + void swapBytesFromHost(support::endianness Endianness); + /*! + * Return the total size of \c ValueProfileData. + */ + uint32_t getSize() const { return TotalSize; } + /*! + * Read data from this data and save it to \c Record. + */ + void deserializeTo(InstrProfRecord &Record, + InstrProfRecord::ValueMapType *VMap); + void operator delete(void *ptr) { ::operator delete(ptr); } +#endif +} ValueProfData; + +/* + * The closure is designed to abstact away two types of value profile data: + * - InstrProfRecord which is the primary data structure used to + * represent profile data in host tools (reader, writer, and profile-use) + * - value profile runtime data structure suitable to be used by C + * runtime library. + * + * Both sources of data need to serialize to disk/memory-buffer in common + * format: ValueProfData. The abstraction allows compiler-rt's raw profiler + * writer to share the same format and code with indexed profile writer. + * + * For documentation of the member methods below, refer to corresponding methods + * in class InstrProfRecord. + */ +typedef struct ValueProfRecordClosure { + const void *Record; + uint32_t (*GetNumValueKinds)(const void *Record); + uint32_t (*GetNumValueSites)(const void *Record, uint32_t VKind); + uint32_t (*GetNumValueData)(const void *Record, uint32_t VKind); + uint32_t (*GetNumValueDataForSite)(const void *R, uint32_t VK, uint32_t S); + + /* + * After extracting the value profile data from the value profile record, + * this method is used to map the in-memory value to on-disk value. If + * the method is null, value will be written out untranslated. + */ + uint64_t (*RemapValueData)(uint32_t, uint64_t Value); + void (*GetValueForSite)(const void *R, InstrProfValueData *Dst, uint32_t K, + uint32_t S, uint64_t (*Mapper)(uint32_t, uint64_t)); + ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes); +} ValueProfRecordClosure; + +/* + * A wrapper struct that represents value profile runtime data. + * Like InstrProfRecord class which is used by profiling host tools, + * ValueProfRuntimeRecord also implements the abstract intefaces defined in + * ValueProfRecordClosure so that the runtime data can be serialized using + * shared C implementation. In this structure, NumValueSites and Nodes + * members are the primary fields while other fields hold the derived + * information for fast implementation of closure interfaces. + */ +typedef struct ValueProfRuntimeRecord { + /* Number of sites for each value profile kind. */ + const uint16_t *NumValueSites; + /* An array of linked-list headers. The size of of the array is the + * total number of value profile sites : sum(NumValueSites[*])). Each + * linked-list stores the values profiled for a value profile site. */ + ValueProfNode **Nodes; + + /* Total number of value profile kinds which have at least one + * value profile sites. */ + uint32_t NumValueKinds; + /* An array recording the number of values tracked at each site. + * The size of the array is TotalNumValueSites. */ + uint8_t *SiteCountArray[IPVK_Last + 1]; + ValueProfNode **NodesKind[IPVK_Last + 1]; +} ValueProfRuntimeRecord; + +/* Forward declarations of C interfaces. */ +int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord, + const uint16_t *NumValueSites, + ValueProfNode **Nodes); +void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord); +uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record); +ValueProfData * +serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record, + ValueProfData *Dst); +uint32_t getNumValueKindsRT(const void *R); + +#undef INSTR_PROF_VALUE_PROF_DATA +#endif /* INSTR_PROF_VALUE_PROF_DATA */ + + +#ifdef INSTR_PROF_COMMON_API_IMPL +#define INSTR_PROF_DATA_DEFINED +#ifdef __cplusplus +#define INSTR_PROF_INLINE inline +#else +#define INSTR_PROF_INLINE +#endif + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +/*! + * \brief Return the \c ValueProfRecord header size including the + * padding bytes. + */ +INSTR_PROF_INLINE +uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites) { + uint32_t Size = offsetof(ValueProfRecord, SiteCountArray) + + sizeof(uint8_t) * NumValueSites; + /* Round the size to multiple of 8 bytes. */ + Size = (Size + 7) & ~7; + return Size; +} + +/*! + * \brief Return the total size of the value profile record including the + * header and the value data. + */ +INSTR_PROF_INLINE +uint32_t getValueProfRecordSize(uint32_t NumValueSites, + uint32_t NumValueData) { + return getValueProfRecordHeaderSize(NumValueSites) + + sizeof(InstrProfValueData) * NumValueData; +} + +/*! + * \brief Return the pointer to the start of value data array. + */ +INSTR_PROF_INLINE +InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) { + return (InstrProfValueData *)((char *)This + getValueProfRecordHeaderSize( + This->NumValueSites)); +} + +/*! + * \brief Return the total number of value data for \c This record. + */ +INSTR_PROF_INLINE +uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) { + uint32_t NumValueData = 0; + uint32_t I; + for (I = 0; I < This->NumValueSites; I++) + NumValueData += This->SiteCountArray[I]; + return NumValueData; +} + +/*! + * \brief Use this method to advance to the next \c This \c ValueProfRecord. + */ +INSTR_PROF_INLINE +ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) { + uint32_t NumValueData = getValueProfRecordNumValueData(This); + return (ValueProfRecord *)((char *)This + + getValueProfRecordSize(This->NumValueSites, + NumValueData)); +} + +/*! + * \brief Return the first \c ValueProfRecord instance. + */ +INSTR_PROF_INLINE +ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) { + return (ValueProfRecord *)((char *)This + sizeof(ValueProfData)); +} + +/* Closure based interfaces. */ + +/*! + * Return the total size in bytes of the on-disk value profile data + * given the data stored in Record. + */ +uint32_t getValueProfDataSize(ValueProfRecordClosure *Closure) { + uint32_t Kind; + uint32_t TotalSize = sizeof(ValueProfData); + const void *Record = Closure->Record; + uint32_t NumValueKinds = Closure->GetNumValueKinds(Record); + if (NumValueKinds == 0) + return TotalSize; + + for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) { + uint32_t NumValueSites = Closure->GetNumValueSites(Record, Kind); + if (!NumValueSites) + continue; + TotalSize += getValueProfRecordSize(NumValueSites, + Closure->GetNumValueData(Record, Kind)); + } + return TotalSize; +} + +/*! + * Extract value profile data of a function for the profile kind \c ValueKind + * from the \c Closure and serialize the data into \c This record instance. + */ +void serializeValueProfRecordFrom(ValueProfRecord *This, + ValueProfRecordClosure *Closure, + uint32_t ValueKind, uint32_t NumValueSites) { + uint32_t S; + const void *Record = Closure->Record; + This->Kind = ValueKind; + This->NumValueSites = NumValueSites; + InstrProfValueData *DstVD = getValueProfRecordValueData(This); + + for (S = 0; S < NumValueSites; S++) { + uint32_t ND = Closure->GetNumValueDataForSite(Record, ValueKind, S); + This->SiteCountArray[S] = ND; + Closure->GetValueForSite(Record, DstVD, ValueKind, S, + Closure->RemapValueData); + DstVD += ND; + } +} + +/*! + * Extract value profile data of a function from the \c Closure + * and serialize the data into \c DstData if it is not NULL or heap + * memory allocated by the \c Closure's allocator method. + */ +ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure, + ValueProfData *DstData) { + uint32_t Kind; + uint32_t TotalSize = getValueProfDataSize(Closure); + + ValueProfData *VPD = + DstData ? DstData : Closure->AllocValueProfData(TotalSize); + + VPD->TotalSize = TotalSize; + VPD->NumValueKinds = Closure->GetNumValueKinds(Closure->Record); + ValueProfRecord *VR = getFirstValueProfRecord(VPD); + for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) { + uint32_t NumValueSites = Closure->GetNumValueSites(Closure->Record, Kind); + if (!NumValueSites) + continue; + serializeValueProfRecordFrom(VR, Closure, Kind, NumValueSites); + VR = getValueProfRecordNext(VR); + } + return VPD; +} + +/* + * The value profiler runtime library stores the value profile data + * for a given function in \c NumValueSites and \c Nodes structures. + * \c ValueProfRuntimeRecord class is used to encapsulate the runtime + * profile data and provides fast interfaces to retrieve the profile + * information. This interface is used to initialize the runtime record + * and pre-compute the information needed for efficient implementation + * of callbacks required by ValueProfRecordClosure class. + */ +int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord, + const uint16_t *NumValueSites, + ValueProfNode **Nodes) { + unsigned I, J, S = 0, NumValueKinds = 0; + RuntimeRecord->NumValueSites = NumValueSites; + RuntimeRecord->Nodes = Nodes; + for (I = 0; I <= IPVK_Last; I++) { + uint16_t N = NumValueSites[I]; + if (!N) { + RuntimeRecord->SiteCountArray[I] = 0; + continue; + } + NumValueKinds++; + RuntimeRecord->SiteCountArray[I] = (uint8_t *)calloc(N, 1); + if (!RuntimeRecord->SiteCountArray[I]) + return 1; + RuntimeRecord->NodesKind[I] = Nodes ? &Nodes[S] : NULL; + for (J = 0; J < N; J++) { + /* Compute value count for each site. */ + uint32_t C = 0; + ValueProfNode *Site = Nodes ? RuntimeRecord->NodesKind[I][J] : NULL; + while (Site) { + C++; + Site = Site->Next; + } + if (C > UCHAR_MAX) + C = UCHAR_MAX; + RuntimeRecord->SiteCountArray[I][J] = C; + } + S += N; + } + RuntimeRecord->NumValueKinds = NumValueKinds; + return 0; +} + +void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord) { + unsigned I; + for (I = 0; I <= IPVK_Last; I++) { + if (RuntimeRecord->SiteCountArray[I]) + free(RuntimeRecord->SiteCountArray[I]); + } +} + +/* ValueProfRecordClosure Interface implementation for + * ValueProfDataRuntimeRecord. */ +uint32_t getNumValueKindsRT(const void *R) { + return ((const ValueProfRuntimeRecord *)R)->NumValueKinds; +} + +uint32_t getNumValueSitesRT(const void *R, uint32_t VK) { + return ((const ValueProfRuntimeRecord *)R)->NumValueSites[VK]; +} + +uint32_t getNumValueDataForSiteRT(const void *R, uint32_t VK, uint32_t S) { + const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R; + return Record->SiteCountArray[VK][S]; +} + +uint32_t getNumValueDataRT(const void *R, uint32_t VK) { + unsigned I, S = 0; + const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R; + if (Record->SiteCountArray[VK] == 0) + return 0; + for (I = 0; I < Record->NumValueSites[VK]; I++) + S += Record->SiteCountArray[VK][I]; + return S; +} + +void getValueForSiteRT(const void *R, InstrProfValueData *Dst, uint32_t VK, + uint32_t S, uint64_t (*Mapper)(uint32_t, uint64_t)) { + unsigned I, N = 0; + const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R; + N = getNumValueDataForSiteRT(R, VK, S); + if (N == 0) + return; + ValueProfNode *VNode = Record->NodesKind[VK][S]; + for (I = 0; I < N; I++) { + Dst[I] = VNode->VData; + VNode = VNode->Next; + } +} + +ValueProfData *allocValueProfDataRT(size_t TotalSizeInBytes) { + return (ValueProfData *)calloc(TotalSizeInBytes, 1); +} + +static ValueProfRecordClosure RTRecordClosure = {0, + getNumValueKindsRT, + getNumValueSitesRT, + getNumValueDataRT, + getNumValueDataForSiteRT, + 0, + getValueForSiteRT, + allocValueProfDataRT}; + +/* + * Return the size of ValueProfData structure to store data + * recorded in the runtime record. + */ +uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record) { + RTRecordClosure.Record = Record; + return getValueProfDataSize(&RTRecordClosure); +} + +/* + * Return a ValueProfData instance that stores the data collected + * from runtime. If \c DstData is provided by the caller, the value + * profile data will be store in *DstData and DstData is returned, + * otherwise the method will allocate space for the value data and + * return pointer to the newly allocated space. + */ +ValueProfData * +serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record, + ValueProfData *DstData) { + RTRecordClosure.Record = Record; + return serializeValueProfDataFrom(&RTRecordClosure, DstData); +} + + +#undef INSTR_PROF_COMMON_API_IMPL +#endif /* INSTR_PROF_COMMON_API_IMPL */ + +/*============================================================================*/ + + +#ifndef INSTR_PROF_DATA_DEFINED + +#ifndef INSTR_PROF_DATA_INC_ +#define INSTR_PROF_DATA_INC_ + +/* Helper macros. */ +#define INSTR_PROF_SIMPLE_QUOTE(x) #x +#define INSTR_PROF_QUOTE(x) INSTR_PROF_SIMPLE_QUOTE(x) +#define INSTR_PROF_SIMPLE_CONCAT(x,y) x ## y +#define INSTR_PROF_CONCAT(x,y) INSTR_PROF_SIMPLE_CONCAT(x,y) + +/* Magic number to detect file format and endianness. + * Use 255 at one end, since no UTF-8 file can use that character. Avoid 0, + * so that utilities, like strings, don't grab it as a string. 129 is also + * invalid UTF-8, and high enough to be interesting. + * Use "lprofr" in the centre to stand for "LLVM Profile Raw", or "lprofR" + * for 32-bit platforms. + */ +#define INSTR_PROF_RAW_MAGIC_64 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \ + (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \ + (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129 +#define INSTR_PROF_RAW_MAGIC_32 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \ + (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \ + (uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129 + +/* Raw profile format version. */ +#define INSTR_PROF_RAW_VERSION 2 +#define INSTR_PROF_INDEX_VERSION 3 +#define INSTR_PROF_COVMAP_VERSION 0 + +/* Profile version is always of type uint_64_t. Reserve the upper 8 bits in the + * version for other variants of profile. We set the lowest bit of the upper 8 + * bits (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentaiton + * generated profile, and 0 if this is a Clang FE generated profile. +*/ +#define VARIANT_MASKS_ALL 0xff00000000000000ULL +#define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL) + +/* Runtime section names and name strings. */ +#define INSTR_PROF_DATA_SECT_NAME __llvm_prf_data +#define INSTR_PROF_NAME_SECT_NAME __llvm_prf_names +#define INSTR_PROF_CNTS_SECT_NAME __llvm_prf_cnts +#define INSTR_PROF_COVMAP_SECT_NAME __llvm_covmap + +#define INSTR_PROF_DATA_SECT_NAME_STR \ + INSTR_PROF_QUOTE(INSTR_PROF_DATA_SECT_NAME) +#define INSTR_PROF_NAME_SECT_NAME_STR \ + INSTR_PROF_QUOTE(INSTR_PROF_NAME_SECT_NAME) +#define INSTR_PROF_CNTS_SECT_NAME_STR \ + INSTR_PROF_QUOTE(INSTR_PROF_CNTS_SECT_NAME) +#define INSTR_PROF_COVMAP_SECT_NAME_STR \ + INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_SECT_NAME) + +/* Macros to define start/stop section symbol for a given + * section on Linux. For instance + * INSTR_PROF_SECT_START(INSTR_PROF_DATA_SECT_NAME) will + * expand to __start___llvm_prof_data + */ +#define INSTR_PROF_SECT_START(Sect) \ + INSTR_PROF_CONCAT(__start_,Sect) +#define INSTR_PROF_SECT_STOP(Sect) \ + INSTR_PROF_CONCAT(__stop_,Sect) + +/* Value Profiling API linkage name. */ +#define INSTR_PROF_VALUE_PROF_FUNC __llvm_profile_instrument_target +#define INSTR_PROF_VALUE_PROF_FUNC_STR \ + INSTR_PROF_QUOTE(INSTR_PROF_VALUE_PROF_FUNC) + +/* InstrProfile per-function control data alignment. */ +#define INSTR_PROF_DATA_ALIGNMENT 8 + +/* The data structure that represents a tracked value by the + * value profiler. + */ +typedef struct InstrProfValueData { + /* Profiled value. */ + uint64_t Value; + /* Number of times the value appears in the training run. */ + uint64_t Count; +} InstrProfValueData; + +/* This is an internal data structure used by value profiler. It + * is defined here to allow serialization code sharing by LLVM + * to be used in unit test. + */ +typedef struct ValueProfNode { + InstrProfValueData VData; + struct ValueProfNode *Next; +} ValueProfNode; + +#endif /* INSTR_PROF_DATA_INC_ */ + +#else +#undef INSTR_PROF_DATA_DEFINED +#endif diff --git a/src/compiler-rt/lib/profile/InstrProfiling.c b/src/compiler-rt/lib/profile/InstrProfiling.c index 8d010df28f..711f2b608a 100644 --- a/src/compiler-rt/lib/profile/InstrProfiling.c +++ b/src/compiler-rt/lib/profile/InstrProfiling.c @@ -8,41 +8,62 @@ \*===----------------------------------------------------------------------===*/ #include "InstrProfiling.h" +#include "InstrProfilingInternal.h" +#include +#include +#include #include +#define INSTR_PROF_VALUE_PROF_DATA +#include "InstrProfData.inc" -__attribute__((visibility("hidden"))) -uint64_t __llvm_profile_get_magic(void) { - /* Magic number to detect file format and endianness. - * - * Use 255 at one end, since no UTF-8 file can use that character. Avoid 0, - * so that utilities, like strings, don't grab it as a string. 129 is also - * invalid UTF-8, and high enough to be interesting. - * - * Use "lprofr" in the centre to stand for "LLVM Profile Raw", or "lprofR" - * for 32-bit platforms. - */ - unsigned char R = sizeof(void *) == sizeof(uint64_t) ? 'r' : 'R'; - return - (uint64_t)255 << 56 | - (uint64_t)'l' << 48 | - (uint64_t)'p' << 40 | - (uint64_t)'r' << 32 | - (uint64_t)'o' << 24 | - (uint64_t)'f' << 16 | - (uint64_t) R << 8 | - (uint64_t)129; +char *(*GetEnvHook)(const char *) = 0; + +COMPILER_RT_WEAK uint64_t __llvm_profile_raw_version = INSTR_PROF_RAW_VERSION; + +COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_magic(void) { + return sizeof(void *) == sizeof(uint64_t) ? (INSTR_PROF_RAW_MAGIC_64) + : (INSTR_PROF_RAW_MAGIC_32); } -__attribute__((visibility("hidden"))) -uint64_t __llvm_profile_get_version(void) { - /* This should be bumped any time the output format changes. */ - return 1; +/* Return the number of bytes needed to add to SizeInBytes to make it + * the result a multiple of 8. + */ +COMPILER_RT_VISIBILITY uint8_t +__llvm_profile_get_num_padding_bytes(uint64_t SizeInBytes) { + return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t)); } -__attribute__((visibility("hidden"))) -void __llvm_profile_reset_counters(void) { +COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_version(void) { + return __llvm_profile_raw_version; +} + +COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) { uint64_t *I = __llvm_profile_begin_counters(); uint64_t *E = __llvm_profile_end_counters(); - memset(I, 0, sizeof(uint64_t)*(E - I)); + memset(I, 0, sizeof(uint64_t) * (E - I)); + + const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); + const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); + const __llvm_profile_data *DI; + for (DI = DataBegin; DI != DataEnd; ++DI) { + uint64_t CurrentVSiteCount = 0; + uint32_t VKI, i; + if (!DI->Values) + continue; + + ValueProfNode **ValueCounters = (ValueProfNode **)DI->Values; + + for (VKI = IPVK_First; VKI <= IPVK_Last; ++VKI) + CurrentVSiteCount += DI->NumValueSites[VKI]; + + for (i = 0; i < CurrentVSiteCount; ++i) { + ValueProfNode *CurrentVNode = ValueCounters[i]; + + while (CurrentVNode) { + CurrentVNode->VData.Count = 0; + CurrentVNode = CurrentVNode->Next; + } + } + } } diff --git a/src/compiler-rt/lib/profile/InstrProfiling.h b/src/compiler-rt/lib/profile/InstrProfiling.h index 7aac3b4c29..d27ca569d5 100644 --- a/src/compiler-rt/lib/profile/InstrProfiling.h +++ b/src/compiler-rt/lib/profile/InstrProfiling.h @@ -10,42 +10,31 @@ #ifndef PROFILE_INSTRPROFILING_H_ #define PROFILE_INSTRPROFILING_H_ -#if defined(__FreeBSD__) && defined(__i386__) - -/* System headers define 'size_t' incorrectly on x64 FreeBSD (prior to - * FreeBSD 10, r232261) when compiled in 32-bit mode. - */ -#define PRIu64 "llu" -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; -typedef uint32_t uintptr_t; - -#else /* defined(__FreeBSD__) && defined(__i386__) */ - -#include -#include - -#endif /* defined(__FreeBSD__) && defined(__i386__) */ - - -typedef struct __llvm_profile_data { - const uint32_t NameSize; - const uint32_t NumCounters; - const uint64_t FuncHash; - const char *const Name; - uint64_t *const Counters; +#include "InstrProfilingPort.h" +#include "InstrProfData.inc" + +enum ValueKind { +#define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value, +#include "InstrProfData.inc" +}; + +typedef void *IntPtrT; +typedef struct COMPILER_RT_ALIGNAS(INSTR_PROF_DATA_ALIGNMENT) + __llvm_profile_data { +#define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) Type Name; +#include "InstrProfData.inc" } __llvm_profile_data; typedef struct __llvm_profile_header { - uint64_t Magic; - uint64_t Version; - uint64_t DataSize; - uint64_t CountersSize; - uint64_t NamesSize; - uint64_t CountersDelta; - uint64_t NamesDelta; +#define INSTR_PROF_RAW_HEADER(Type, Name, Initializer) Type Name; +#include "InstrProfData.inc" } __llvm_profile_header; +/*! + * \brief Get number of bytes necessary to pad the argument to eight + * byte boundary. + */ +uint8_t __llvm_profile_get_num_padding_bytes(uint64_t SizeInBytes); /*! * \brief Get required size for profile buffer. @@ -67,10 +56,38 @@ const char *__llvm_profile_end_names(void); uint64_t *__llvm_profile_begin_counters(void); uint64_t *__llvm_profile_end_counters(void); +/*! + * \brief Clear profile counters to zero. + * + */ +void __llvm_profile_reset_counters(void); + +/*! + * \brief Counts the number of times a target value is seen. + * + * Records the target value for the CounterIndex if not seen before. Otherwise, + * increments the counter associated w/ the target value. + * void __llvm_profile_instrument_target(uint64_t TargetValue, void *Data, + * uint32_t CounterIndex); + */ +void INSTR_PROF_VALUE_PROF_FUNC( +#define VALUE_PROF_FUNC_PARAM(ArgType, ArgName, ArgLLVMType) ArgType ArgName +#include "InstrProfData.inc" +); + +/*! + * \brief Prepares the value profiling data for output. + * + * Returns an array of pointers to value profile data. + */ +struct ValueProfData; +struct ValueProfData **__llvm_profile_gather_value_data(uint64_t *Size); + /*! * \brief Write instrumentation data to the current file. * - * Writes to the file with the last name given to \a __llvm_profile_set_filename(), + * Writes to the file with the last name given to \a * + * __llvm_profile_set_filename(), * or if it hasn't been called, the \c LLVM_PROFILE_FILE environment variable, * or if that's not set, the last name given to * \a __llvm_profile_override_default_filename(), or if that's not set, diff --git a/src/compiler-rt/lib/profile/InstrProfilingBuffer.c b/src/compiler-rt/lib/profile/InstrProfilingBuffer.c index e587932da0..4227ca6b66 100644 --- a/src/compiler-rt/lib/profile/InstrProfilingBuffer.c +++ b/src/compiler-rt/lib/profile/InstrProfilingBuffer.c @@ -10,9 +10,7 @@ #include "InstrProfiling.h" #include "InstrProfilingInternal.h" -#include - -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_size_for_buffer(void) { const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); @@ -27,78 +25,28 @@ uint64_t __llvm_profile_get_size_for_buffer(void) { #define PROFILE_RANGE_SIZE(Range) (Range##End - Range##Begin) -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_size_for_buffer_internal( - const __llvm_profile_data *DataBegin, - const __llvm_profile_data *DataEnd, const uint64_t *CountersBegin, - const uint64_t *CountersEnd, const char *NamesBegin, - const char *NamesEnd) { + const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd, + const uint64_t *CountersBegin, const uint64_t *CountersEnd, + const char *NamesBegin, const char *NamesEnd) { /* Match logic in __llvm_profile_write_buffer(). */ const uint64_t NamesSize = PROFILE_RANGE_SIZE(Names) * sizeof(char); - const uint64_t Padding = sizeof(uint64_t) - NamesSize % sizeof(uint64_t); + const uint8_t Padding = __llvm_profile_get_num_padding_bytes(NamesSize); return sizeof(__llvm_profile_header) + - PROFILE_RANGE_SIZE(Data) * sizeof(__llvm_profile_data) + - PROFILE_RANGE_SIZE(Counters) * sizeof(uint64_t) + - NamesSize + Padding; + PROFILE_RANGE_SIZE(Data) * sizeof(__llvm_profile_data) + + PROFILE_RANGE_SIZE(Counters) * sizeof(uint64_t) + NamesSize + Padding; } -__attribute__((visibility("hidden"))) -int __llvm_profile_write_buffer(char *Buffer) { - /* Match logic in __llvm_profile_get_size_for_buffer(). - * Match logic in __llvm_profile_write_file(). - */ - const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); - const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); - const uint64_t *CountersBegin = __llvm_profile_begin_counters(); - const uint64_t *CountersEnd = __llvm_profile_end_counters(); - const char *NamesBegin = __llvm_profile_begin_names(); - const char *NamesEnd = __llvm_profile_end_names(); - - return __llvm_profile_write_buffer_internal(Buffer, DataBegin, DataEnd, - CountersBegin, CountersEnd, - NamesBegin, NamesEnd); +COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer(char *Buffer) { + return llvmWriteProfData(llvmBufferWriter, Buffer, 0, 0); } -__attribute__((visibility("hidden"))) -int __llvm_profile_write_buffer_internal( +COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal( char *Buffer, const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd, const uint64_t *CountersBegin, const uint64_t *CountersEnd, const char *NamesBegin, const char *NamesEnd) { - /* Match logic in __llvm_profile_get_size_for_buffer(). - * Match logic in __llvm_profile_write_file(). - */ - - /* Calculate size of sections. */ - const uint64_t DataSize = DataEnd - DataBegin; - const uint64_t CountersSize = CountersEnd - CountersBegin; - const uint64_t NamesSize = NamesEnd - NamesBegin; - const uint64_t Padding = sizeof(uint64_t) - NamesSize % sizeof(uint64_t); - - /* Enough zeroes for padding. */ - const char Zeroes[sizeof(uint64_t)] = {0}; - - /* Create the header. */ - __llvm_profile_header Header; - Header.Magic = __llvm_profile_get_magic(); - Header.Version = __llvm_profile_get_version(); - Header.DataSize = DataSize; - Header.CountersSize = CountersSize; - Header.NamesSize = NamesSize; - Header.CountersDelta = (uintptr_t)CountersBegin; - Header.NamesDelta = (uintptr_t)NamesBegin; - - /* Write the data. */ -#define UPDATE_memcpy(Data, Size) \ - do { \ - memcpy(Buffer, Data, Size); \ - Buffer += Size; \ - } while (0) - UPDATE_memcpy(&Header, sizeof(__llvm_profile_header)); - UPDATE_memcpy(DataBegin, DataSize * sizeof(__llvm_profile_data)); - UPDATE_memcpy(CountersBegin, CountersSize * sizeof(uint64_t)); - UPDATE_memcpy(NamesBegin, NamesSize * sizeof(char)); - UPDATE_memcpy(Zeroes, Padding * sizeof(char)); -#undef UPDATE_memcpy - - return 0; + return llvmWriteProfDataImpl(llvmBufferWriter, Buffer, DataBegin, DataEnd, + CountersBegin, CountersEnd, 0, 0, NamesBegin, + NamesEnd); } diff --git a/src/compiler-rt/lib/profile/InstrProfilingFile.c b/src/compiler-rt/lib/profile/InstrProfilingFile.c index 6af835e484..68d088a195 100644 --- a/src/compiler-rt/lib/profile/InstrProfilingFile.c +++ b/src/compiler-rt/lib/profile/InstrProfilingFile.c @@ -8,6 +8,7 @@ \*===----------------------------------------------------------------------===*/ #include "InstrProfiling.h" +#include "InstrProfilingInternal.h" #include "InstrProfilingUtil.h" #include #include @@ -16,47 +17,43 @@ #define UNCONST(ptr) ((void *)(uintptr_t)(ptr)) -static int writeFile(FILE *File) { - /* Match logic in __llvm_profile_write_buffer(). */ - const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); - const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); - const uint64_t *CountersBegin = __llvm_profile_begin_counters(); - const uint64_t *CountersEnd = __llvm_profile_end_counters(); - const char *NamesBegin = __llvm_profile_begin_names(); - const char *NamesEnd = __llvm_profile_end_names(); - - /* Calculate size of sections. */ - const uint64_t DataSize = DataEnd - DataBegin; - const uint64_t CountersSize = CountersEnd - CountersBegin; - const uint64_t NamesSize = NamesEnd - NamesBegin; - const uint64_t Padding = sizeof(uint64_t) - NamesSize % sizeof(uint64_t); - - /* Enough zeroes for padding. */ - const char Zeroes[sizeof(uint64_t)] = {0}; - - /* Create the header. */ - __llvm_profile_header Header; - Header.Magic = __llvm_profile_get_magic(); - Header.Version = __llvm_profile_get_version(); - Header.DataSize = DataSize; - Header.CountersSize = CountersSize; - Header.NamesSize = NamesSize; - Header.CountersDelta = (uintptr_t)CountersBegin; - Header.NamesDelta = (uintptr_t)NamesBegin; - - /* Write the data. */ -#define CHECK_fwrite(Data, Size, Length, File) \ - do { if (fwrite(Data, Size, Length, File) != Length) return -1; } while (0) - CHECK_fwrite(&Header, sizeof(__llvm_profile_header), 1, File); - CHECK_fwrite(DataBegin, sizeof(__llvm_profile_data), DataSize, File); - CHECK_fwrite(CountersBegin, sizeof(uint64_t), CountersSize, File); - CHECK_fwrite(NamesBegin, sizeof(char), NamesSize, File); - CHECK_fwrite(Zeroes, sizeof(char), Padding, File); -#undef CHECK_fwrite - +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +/* Return 1 if there is an error, otherwise return 0. */ +static uint32_t fileWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs, + void **WriterCtx) { + uint32_t I; + FILE *File = (FILE *)*WriterCtx; + for (I = 0; I < NumIOVecs; I++) { + if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) != + IOVecs[I].NumElm) + return 1; + } return 0; } +COMPILER_RT_VISIBILITY ProfBufferIO * +llvmCreateBufferIOInternal(void *File, uint32_t BufferSz) { + CallocHook = calloc; + FreeHook = free; + return llvmCreateBufferIO(fileWriter, File, BufferSz); +} + +static int writeFile(FILE *File) { + const char *BufferSzStr = 0; + uint64_t ValueDataSize = 0; + struct ValueProfData **ValueDataArray = + __llvm_profile_gather_value_data(&ValueDataSize); + FreeHook = &free; + CallocHook = &calloc; + BufferSzStr = getenv("LLVM_VP_BUFFER_SIZE"); + if (BufferSzStr && BufferSzStr[0]) + VPBufferSize = atoi(BufferSzStr); + return llvmWriteProfData(fileWriter, File, ValueDataArray, ValueDataSize); +} + static int writeFileWithName(const char *OutputName) { int RetVal; FILE *OutputFile; @@ -64,7 +61,7 @@ static int writeFileWithName(const char *OutputName) { return -1; /* Append to the file to support profiling multiple shared objects. */ - OutputFile = fopen(OutputName, "a"); + OutputFile = fopen(OutputName, "ab"); if (!OutputFile) return -1; @@ -74,8 +71,8 @@ static int writeFileWithName(const char *OutputName) { return RetVal; } -__attribute__((weak)) int __llvm_profile_OwnsFilename = 0; -__attribute__((weak)) const char *__llvm_profile_CurrentFilename = NULL; +COMPILER_RT_WEAK int __llvm_profile_OwnsFilename = 0; +COMPILER_RT_WEAK const char *__llvm_profile_CurrentFilename = NULL; static void truncateCurrentFile(void) { const char *Filename; @@ -182,7 +179,7 @@ static void setFilenameAutomatically(void) { resetFilenameToDefault(); } -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY void __llvm_profile_initialize_file(void) { /* Check if the filename has been initialized. */ if (__llvm_profile_CurrentFilename) @@ -192,12 +189,12 @@ void __llvm_profile_initialize_file(void) { setFilenameAutomatically(); } -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY void __llvm_profile_set_filename(const char *Filename) { setFilenamePossiblyWithPid(Filename); } -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY void __llvm_profile_override_default_filename(const char *Filename) { /* If the env var is set, skip setting filename from argument. */ const char *Env_Filename = getenv("LLVM_PROFILE_FILE"); @@ -206,27 +203,37 @@ void __llvm_profile_override_default_filename(const char *Filename) { setFilenamePossiblyWithPid(Filename); } -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY int __llvm_profile_write_file(void) { int rc; + GetEnvHook = &getenv; /* Check the filename. */ - if (!__llvm_profile_CurrentFilename) + if (!__llvm_profile_CurrentFilename) { + PROF_ERR("LLVM Profile: Failed to write file : %s\n", "Filename not set"); + return -1; + } + + /* Check if there is llvm/runtime version mismatch. */ + if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) { + PROF_ERR("LLVM Profile: runtime and instrumentation version mismatch : " + "expected %d, but get %d\n", + INSTR_PROF_RAW_VERSION, + (int)GET_VERSION(__llvm_profile_get_version())); return -1; + } /* Write the file. */ rc = writeFileWithName(__llvm_profile_CurrentFilename); - if (rc && getenv("LLVM_PROFILE_VERBOSE_ERRORS")) - fprintf(stderr, "LLVM Profile: Failed to write file \"%s\": %s\n", + if (rc) + PROF_ERR("LLVM Profile: Failed to write file \"%s\": %s\n", __llvm_profile_CurrentFilename, strerror(errno)); return rc; } -static void writeFileWithoutReturn(void) { - __llvm_profile_write_file(); -} +static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); } -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY int __llvm_profile_register_write_file_atexit(void) { static int HasBeenRegistered = 0; diff --git a/src/compiler-rt/lib/profile/InstrProfilingInternal.h b/src/compiler-rt/lib/profile/InstrProfilingInternal.h index ede39cd9d7..4aab78ea50 100644 --- a/src/compiler-rt/lib/profile/InstrProfilingInternal.h +++ b/src/compiler-rt/lib/profile/InstrProfilingInternal.h @@ -11,6 +11,7 @@ #define PROFILE_INSTRPROFILING_INTERNALH_ #include "InstrProfiling.h" +#include "stddef.h" /*! * \brief Write instrumentation data to the given buffer, given explicit @@ -37,4 +38,81 @@ int __llvm_profile_write_buffer_internal( const __llvm_profile_data *DataEnd, const uint64_t *CountersBegin, const uint64_t *CountersEnd, const char *NamesBegin, const char *NamesEnd); +/*! + * The data structure describing the data to be written by the + * low level writer callback function. + */ +typedef struct ProfDataIOVec { + const void *Data; + size_t ElmSize; + size_t NumElm; +} ProfDataIOVec; + +typedef uint32_t (*WriterCallback)(ProfDataIOVec *, uint32_t NumIOVecs, + void **WriterCtx); + +/*! + * The data structure for buffered IO of profile data. + */ +typedef struct ProfBufferIO { + /* File handle. */ + void *File; + /* Low level IO callback. */ + WriterCallback FileWriter; + /* The start of the buffer. */ + uint8_t *BufferStart; + /* Total size of the buffer. */ + uint32_t BufferSz; + /* Current byte offset from the start of the buffer. */ + uint32_t CurOffset; +} ProfBufferIO; + +/* The creator interface used by testing. */ +ProfBufferIO *llvmCreateBufferIOInternal(void *File, uint32_t DefaultBufferSz); +/*! + * This is the interface to create a handle for buffered IO. + */ +ProfBufferIO *llvmCreateBufferIO(WriterCallback FileWriter, void *File, + uint32_t DefaultBufferSz); +/*! + * The interface to destroy the bufferIO handle and reclaim + * the memory. + */ +void llvmDeleteBufferIO(ProfBufferIO *BufferIO); + +/*! + * This is the interface to write \c Data of \c Size bytes through + * \c BufferIO. Returns 0 if successful, otherwise return -1. + */ +int llvmBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, + uint32_t Size); +/*! + * The interface to flush the remaining data in the buffer. + * through the low level writer callback. + */ +int llvmBufferIOFlush(ProfBufferIO *BufferIO); + +/* The low level interface to write data into a buffer. It is used as the + * callback by other high level writer methods such as buffered IO writer + * and profile data writer. */ +uint32_t llvmBufferWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs, + void **WriterCtx); + +int llvmWriteProfData(WriterCallback Writer, void *WriterCtx, + struct ValueProfData **ValueDataArray, + const uint64_t ValueDataSize); +int llvmWriteProfDataImpl(WriterCallback Writer, void *WriterCtx, + const __llvm_profile_data *DataBegin, + const __llvm_profile_data *DataEnd, + const uint64_t *CountersBegin, + const uint64_t *CountersEnd, + struct ValueProfData **ValueDataBeginArray, + const uint64_t ValueDataSize, const char *NamesBegin, + const char *NamesEnd); + +extern char *(*GetEnvHook)(const char *); +extern void (*FreeHook)(void *); +extern void* (*CallocHook)(size_t, size_t); +extern uint32_t VPBufferSize; + #endif diff --git a/src/compiler-rt/lib/profile/InstrProfilingPlatformDarwin.c b/src/compiler-rt/lib/profile/InstrProfilingPlatformDarwin.c index 02299cc463..30ddbd2e49 100644 --- a/src/compiler-rt/lib/profile/InstrProfilingPlatformDarwin.c +++ b/src/compiler-rt/lib/profile/InstrProfilingPlatformDarwin.c @@ -11,33 +11,36 @@ #if defined(__APPLE__) /* Use linker magic to find the bounds of the Data section. */ -__attribute__((visibility("hidden"))) -extern __llvm_profile_data DataStart __asm("section$start$__DATA$__llvm_prf_data"); -__attribute__((visibility("hidden"))) -extern __llvm_profile_data DataEnd __asm("section$end$__DATA$__llvm_prf_data"); -__attribute__((visibility("hidden"))) -extern char NamesStart __asm("section$start$__DATA$__llvm_prf_names"); -__attribute__((visibility("hidden"))) -extern char NamesEnd __asm("section$end$__DATA$__llvm_prf_names"); -__attribute__((visibility("hidden"))) -extern uint64_t CountersStart __asm("section$start$__DATA$__llvm_prf_cnts"); -__attribute__((visibility("hidden"))) -extern uint64_t CountersEnd __asm("section$end$__DATA$__llvm_prf_cnts"); +COMPILER_RT_VISIBILITY +extern __llvm_profile_data + DataStart __asm("section$start$__DATA$" INSTR_PROF_DATA_SECT_NAME_STR); +COMPILER_RT_VISIBILITY +extern __llvm_profile_data + DataEnd __asm("section$end$__DATA$" INSTR_PROF_DATA_SECT_NAME_STR); +COMPILER_RT_VISIBILITY +extern char + NamesStart __asm("section$start$__DATA$" INSTR_PROF_NAME_SECT_NAME_STR); +COMPILER_RT_VISIBILITY +extern char NamesEnd __asm("section$end$__DATA$" INSTR_PROF_NAME_SECT_NAME_STR); +COMPILER_RT_VISIBILITY +extern uint64_t + CountersStart __asm("section$start$__DATA$" INSTR_PROF_CNTS_SECT_NAME_STR); +COMPILER_RT_VISIBILITY +extern uint64_t + CountersEnd __asm("section$end$__DATA$" INSTR_PROF_CNTS_SECT_NAME_STR); -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY const __llvm_profile_data *__llvm_profile_begin_data(void) { return &DataStart; } -__attribute__((visibility("hidden"))) -const __llvm_profile_data *__llvm_profile_end_data(void) { - return &DataEnd; -} -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY +const __llvm_profile_data *__llvm_profile_end_data(void) { return &DataEnd; } +COMPILER_RT_VISIBILITY const char *__llvm_profile_begin_names(void) { return &NamesStart; } -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY const char *__llvm_profile_end_names(void) { return &NamesEnd; } -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY uint64_t *__llvm_profile_begin_counters(void) { return &CountersStart; } -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY uint64_t *__llvm_profile_end_counters(void) { return &CountersEnd; } #endif diff --git a/src/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/src/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c index 7a74e0e45f..7843f47caa 100644 --- a/src/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c +++ b/src/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c @@ -12,37 +12,48 @@ #if defined(__linux__) || defined(__FreeBSD__) #include -extern __llvm_profile_data __start___llvm_prf_data - __attribute__((visibility("hidden"))); -extern __llvm_profile_data __stop___llvm_prf_data - __attribute__((visibility("hidden"))); -extern uint64_t __start___llvm_prf_cnts __attribute__((visibility("hidden"))); -extern uint64_t __stop___llvm_prf_cnts __attribute__((visibility("hidden"))); -extern char __start___llvm_prf_names __attribute__((visibility("hidden"))); -extern char __stop___llvm_prf_names __attribute__((visibility("hidden"))); +#define PROF_DATA_START INSTR_PROF_SECT_START(INSTR_PROF_DATA_SECT_NAME) +#define PROF_DATA_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_DATA_SECT_NAME) +#define PROF_NAME_START INSTR_PROF_SECT_START(INSTR_PROF_NAME_SECT_NAME) +#define PROF_NAME_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_NAME_SECT_NAME) +#define PROF_CNTS_START INSTR_PROF_SECT_START(INSTR_PROF_CNTS_SECT_NAME) +#define PROF_CNTS_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_CNTS_SECT_NAME) -__attribute__((visibility("hidden"))) const __llvm_profile_data * +/* Declare section start and stop symbols for various sections + * generated by compiler instrumentation. + */ +extern __llvm_profile_data PROF_DATA_START COMPILER_RT_VISIBILITY; +extern __llvm_profile_data PROF_DATA_STOP COMPILER_RT_VISIBILITY; +extern uint64_t PROF_CNTS_START COMPILER_RT_VISIBILITY; +extern uint64_t PROF_CNTS_STOP COMPILER_RT_VISIBILITY; +extern char PROF_NAME_START COMPILER_RT_VISIBILITY; +extern char PROF_NAME_STOP COMPILER_RT_VISIBILITY; + +/* Add dummy data to ensure the section is always created. */ +__llvm_profile_data + __prof_data_sect_data[0] COMPILER_RT_SECTION(INSTR_PROF_DATA_SECT_NAME_STR); +uint64_t + __prof_cnts_sect_data[0] COMPILER_RT_SECTION(INSTR_PROF_CNTS_SECT_NAME_STR); +char __prof_nms_sect_data[0] COMPILER_RT_SECTION(INSTR_PROF_NAME_SECT_NAME_STR); + +COMPILER_RT_VISIBILITY const __llvm_profile_data * __llvm_profile_begin_data(void) { - return &__start___llvm_prf_data; + return &PROF_DATA_START; } -__attribute__((visibility("hidden"))) const __llvm_profile_data * +COMPILER_RT_VISIBILITY const __llvm_profile_data * __llvm_profile_end_data(void) { - return &__stop___llvm_prf_data; + return &PROF_DATA_STOP; } -__attribute__((visibility("hidden"))) const char *__llvm_profile_begin_names( - void) { - return &__start___llvm_prf_names; +COMPILER_RT_VISIBILITY const char *__llvm_profile_begin_names(void) { + return &PROF_NAME_START; } -__attribute__((visibility("hidden"))) const char *__llvm_profile_end_names( - void) { - return &__stop___llvm_prf_names; +COMPILER_RT_VISIBILITY const char *__llvm_profile_end_names(void) { + return &PROF_NAME_STOP; } -__attribute__((visibility("hidden"))) uint64_t *__llvm_profile_begin_counters( - void) { - return &__start___llvm_prf_cnts; +COMPILER_RT_VISIBILITY uint64_t *__llvm_profile_begin_counters(void) { + return &PROF_CNTS_START; } -__attribute__((visibility("hidden"))) uint64_t *__llvm_profile_end_counters( - void) { - return &__stop___llvm_prf_cnts; +COMPILER_RT_VISIBILITY uint64_t *__llvm_profile_end_counters(void) { + return &PROF_CNTS_STOP; } #endif diff --git a/src/compiler-rt/lib/profile/InstrProfilingPlatformOther.c b/src/compiler-rt/lib/profile/InstrProfilingPlatformOther.c index 2ad058beb9..58ceb3458a 100644 --- a/src/compiler-rt/lib/profile/InstrProfilingPlatformOther.c +++ b/src/compiler-rt/lib/profile/InstrProfilingPlatformOther.c @@ -26,49 +26,43 @@ static uint64_t *CountersLast = NULL; * calls are only required (and only emitted) on targets where we haven't * implemented linker magic to find the bounds of the sections. */ -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY void __llvm_profile_register_function(void *Data_) { /* TODO: Only emit this function if we can't use linker magic. */ - const __llvm_profile_data *Data = (__llvm_profile_data*)Data_; + const __llvm_profile_data *Data = (__llvm_profile_data *)Data_; if (!DataFirst) { DataFirst = Data; DataLast = Data + 1; - NamesFirst = Data->Name; - NamesLast = Data->Name + Data->NameSize; - CountersFirst = Data->Counters; - CountersLast = Data->Counters + Data->NumCounters; + NamesFirst = Data->NamePtr; + NamesLast = (const char *)Data->NamePtr + Data->NameSize; + CountersFirst = Data->CounterPtr; + CountersLast = (uint64_t *)Data->CounterPtr + Data->NumCounters; return; } -#define UPDATE_FIRST(First, New) \ - First = New < First ? New : First +#define UPDATE_FIRST(First, New) First = New < First ? New : First UPDATE_FIRST(DataFirst, Data); - UPDATE_FIRST(NamesFirst, Data->Name); - UPDATE_FIRST(CountersFirst, Data->Counters); + UPDATE_FIRST(NamesFirst, (const char *)Data->NamePtr); + UPDATE_FIRST(CountersFirst, (uint64_t *)Data->CounterPtr); #undef UPDATE_FIRST -#define UPDATE_LAST(Last, New) \ - Last = New > Last ? New : Last +#define UPDATE_LAST(Last, New) Last = New > Last ? New : Last UPDATE_LAST(DataLast, Data + 1); - UPDATE_LAST(NamesLast, Data->Name + Data->NameSize); - UPDATE_LAST(CountersLast, Data->Counters + Data->NumCounters); + UPDATE_LAST(NamesLast, (const char *)Data->NamePtr + Data->NameSize); + UPDATE_LAST(CountersLast, (uint64_t *)Data->CounterPtr + Data->NumCounters); #undef UPDATE_LAST } -__attribute__((visibility("hidden"))) -const __llvm_profile_data *__llvm_profile_begin_data(void) { - return DataFirst; -} -__attribute__((visibility("hidden"))) -const __llvm_profile_data *__llvm_profile_end_data(void) { - return DataLast; -} -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY +const __llvm_profile_data *__llvm_profile_begin_data(void) { return DataFirst; } +COMPILER_RT_VISIBILITY +const __llvm_profile_data *__llvm_profile_end_data(void) { return DataLast; } +COMPILER_RT_VISIBILITY const char *__llvm_profile_begin_names(void) { return NamesFirst; } -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY const char *__llvm_profile_end_names(void) { return NamesLast; } -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY uint64_t *__llvm_profile_begin_counters(void) { return CountersFirst; } -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY uint64_t *__llvm_profile_end_counters(void) { return CountersLast; } #endif diff --git a/src/compiler-rt/lib/profile/InstrProfilingPort.h b/src/compiler-rt/lib/profile/InstrProfilingPort.h new file mode 100644 index 0000000000..e07f598787 --- /dev/null +++ b/src/compiler-rt/lib/profile/InstrProfilingPort.h @@ -0,0 +1,62 @@ +/*===- InstrProfilingPort.h- Support library for PGO instrumentation ------===*\ +|* +|* The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +\*===----------------------------------------------------------------------===*/ + +#ifndef PROFILE_INSTRPROFILING_PORT_H_ +#define PROFILE_INSTRPROFILING_PORT_H_ + +#ifdef _MSC_VER +#define COMPILER_RT_ALIGNAS(x) __declspec(align(x)) +#define COMPILER_RT_VISIBILITY +#define COMPILER_RT_WEAK __declspec(selectany) +#elif __GNUC__ +#define COMPILER_RT_ALIGNAS(x) __attribute__((aligned(x))) +#define COMPILER_RT_VISIBILITY __attribute__((visibility("hidden"))) +#define COMPILER_RT_WEAK __attribute__((weak)) +#endif + +#define COMPILER_RT_SECTION(Sect) __attribute__((section(Sect))) + +#if COMPILER_RT_HAS_ATOMICS == 1 +#ifdef _MSC_VER +#include +#if defined(_WIN64) +#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \ + (InterlockedCompareExchange64((LONGLONG volatile *)Ptr, (LONGLONG)NewV, \ + (LONGLONG)OldV) == (LONGLONG)OldV) +#else /* !defined(_WIN64) */ +#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \ + (InterlockedCompareExchange((LONG volatile *)Ptr, (LONG)NewV, (LONG)OldV) == \ + (LONG)OldV) +#endif +#else /* !defined(_MSC_VER) */ +#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \ + __sync_bool_compare_and_swap(Ptr, OldV, NewV) +#endif +#else /* COMPILER_RT_HAS_ATOMICS != 1 */ +#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \ + BoolCmpXchg((void **)Ptr, OldV, NewV) +#endif + +#define PROF_ERR(Format, ...) \ + if (GetEnvHook && GetEnvHook("LLVM_PROFILE_VERBOSE_ERRORS")) \ + fprintf(stderr, Format, __VA_ARGS__); + +#if defined(__FreeBSD__) + +#include +#include + +#else /* defined(__FreeBSD__) */ + +#include +#include + +#endif /* defined(__FreeBSD__) && defined(__i386__) */ + +#endif /* PROFILE_INSTRPROFILING_PORT_H_ */ diff --git a/src/compiler-rt/lib/profile/InstrProfilingRuntime.cc b/src/compiler-rt/lib/profile/InstrProfilingRuntime.cc index 081ecb29e9..12ad9f1573 100644 --- a/src/compiler-rt/lib/profile/InstrProfilingRuntime.cc +++ b/src/compiler-rt/lib/profile/InstrProfilingRuntime.cc @@ -11,8 +11,7 @@ extern "C" { #include "InstrProfiling.h" -__attribute__((visibility("hidden"))) int __llvm_profile_runtime; - +COMPILER_RT_VISIBILITY int __llvm_profile_runtime; } namespace { diff --git a/src/compiler-rt/lib/profile/InstrProfilingUtil.c b/src/compiler-rt/lib/profile/InstrProfilingUtil.c index e146dfca83..6f0443d3bb 100644 --- a/src/compiler-rt/lib/profile/InstrProfilingUtil.c +++ b/src/compiler-rt/lib/profile/InstrProfilingUtil.c @@ -8,6 +8,7 @@ \*===----------------------------------------------------------------------===*/ #include "InstrProfilingUtil.h" +#include "InstrProfiling.h" #ifdef _WIN32 #include @@ -18,7 +19,7 @@ int mkdir(const char*, unsigned short); #include #endif -__attribute__((visibility("hidden"))) +COMPILER_RT_VISIBILITY void __llvm_profile_recursive_mkdir(char *path) { int i; diff --git a/src/compiler-rt/lib/profile/InstrProfilingValue.c b/src/compiler-rt/lib/profile/InstrProfilingValue.c new file mode 100644 index 0000000000..68e16cff9c --- /dev/null +++ b/src/compiler-rt/lib/profile/InstrProfilingValue.c @@ -0,0 +1,180 @@ +/*===- InstrProfilingValue.c - Support library for PGO instrumentation ----===*\ +|* +|* The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +\*===----------------------------------------------------------------------===*/ + +#include "InstrProfiling.h" +#include "InstrProfilingInternal.h" +#include +#include +#include +#include +#define INSTR_PROF_VALUE_PROF_DATA +#define INSTR_PROF_COMMON_API_IMPL +#include "InstrProfData.inc" + +#define PROF_OOM(Msg) PROF_ERR(Msg ":%s\n", "Out of memory"); +#define PROF_OOM_RETURN(Msg) \ + { \ + PROF_OOM(Msg) \ + free(ValueDataArray); \ + return NULL; \ + } + +#if COMPILER_RT_HAS_ATOMICS != 1 +COMPILER_RT_VISIBILITY +uint32_t BoolCmpXchg(void **Ptr, void *OldV, void *NewV) { + void *R = *Ptr; + if (R == OldV) { + *Ptr = NewV; + return 1; + } + return 0; +} +#endif + +/* This method is only used in value profiler mock testing. */ +COMPILER_RT_VISIBILITY void +__llvm_profile_set_num_value_sites(__llvm_profile_data *Data, + uint32_t ValueKind, uint16_t NumValueSites) { + *((uint16_t *)&Data->NumValueSites[ValueKind]) = NumValueSites; +} + +/* This method is only used in value profiler mock testing. */ +COMPILER_RT_VISIBILITY const __llvm_profile_data * +__llvm_profile_iterate_data(const __llvm_profile_data *Data) { + return Data + 1; +} + +/* This method is only used in value profiler mock testing. */ +COMPILER_RT_VISIBILITY void * +__llvm_get_function_addr(const __llvm_profile_data *Data) { + return Data->FunctionPointer; +} + +/* Allocate an array that holds the pointers to the linked lists of + * value profile counter nodes. The number of element of the array + * is the total number of value profile sites instrumented. Returns + * 0 if allocation fails. + */ + +static int allocateValueProfileCounters(__llvm_profile_data *Data) { + uint64_t NumVSites = 0; + uint32_t VKI; + for (VKI = IPVK_First; VKI <= IPVK_Last; ++VKI) + NumVSites += Data->NumValueSites[VKI]; + + ValueProfNode **Mem = + (ValueProfNode **)calloc(NumVSites, sizeof(ValueProfNode *)); + if (!Mem) + return 0; + if (!COMPILER_RT_BOOL_CMPXCHG(&Data->Values, 0, Mem)) { + free(Mem); + return 0; + } + return 1; +} + +COMPILER_RT_VISIBILITY void +__llvm_profile_instrument_target(uint64_t TargetValue, void *Data, + uint32_t CounterIndex) { + + __llvm_profile_data *PData = (__llvm_profile_data *)Data; + if (!PData) + return; + + if (!PData->Values) { + if (!allocateValueProfileCounters(PData)) + return; + } + + ValueProfNode **ValueCounters = (ValueProfNode **)PData->Values; + ValueProfNode *PrevVNode = NULL; + ValueProfNode *CurrentVNode = ValueCounters[CounterIndex]; + + uint8_t VDataCount = 0; + while (CurrentVNode) { + if (TargetValue == CurrentVNode->VData.Value) { + CurrentVNode->VData.Count++; + return; + } + PrevVNode = CurrentVNode; + CurrentVNode = CurrentVNode->Next; + ++VDataCount; + } + + if (VDataCount >= INSTR_PROF_MAX_NUM_VAL_PER_SITE) + return; + + CurrentVNode = (ValueProfNode *)calloc(1, sizeof(ValueProfNode)); + if (!CurrentVNode) + return; + + CurrentVNode->VData.Value = TargetValue; + CurrentVNode->VData.Count++; + + uint32_t Success = 0; + if (!ValueCounters[CounterIndex]) + Success = + COMPILER_RT_BOOL_CMPXCHG(&ValueCounters[CounterIndex], 0, CurrentVNode); + else if (PrevVNode && !PrevVNode->Next) + Success = COMPILER_RT_BOOL_CMPXCHG(&(PrevVNode->Next), 0, CurrentVNode); + + if (!Success) { + free(CurrentVNode); + return; + } +} + +COMPILER_RT_VISIBILITY ValueProfData ** +__llvm_profile_gather_value_data(uint64_t *ValueDataSize) { + size_t S = 0; + __llvm_profile_data *I; + ValueProfData **ValueDataArray; + + const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); + const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); + + if (!ValueDataSize) + return NULL; + + ValueDataArray = + (ValueProfData **)calloc(DataEnd - DataBegin, sizeof(void *)); + if (!ValueDataArray) + PROF_OOM_RETURN("Failed to write value profile data "); + + /* + * Compute the total Size of the buffer to hold ValueProfData + * structures for functions with value profile data. + */ + for (I = (__llvm_profile_data *)DataBegin; I != DataEnd; ++I) { + ValueProfRuntimeRecord R; + if (initializeValueProfRuntimeRecord(&R, I->NumValueSites, I->Values)) + PROF_OOM_RETURN("Failed to write value profile data "); + + /* Compute the size of ValueProfData from this runtime record. */ + if (getNumValueKindsRT(&R) != 0) { + ValueProfData *VD = NULL; + uint32_t VS = getValueProfDataSizeRT(&R); + VD = (ValueProfData *)calloc(VS, sizeof(uint8_t)); + if (!VD) + PROF_OOM_RETURN("Failed to write value profile data "); + serializeValueProfDataFromRT(&R, VD); + ValueDataArray[I - DataBegin] = VD; + S += VS; + } + finalizeValueProfRuntimeRecord(&R); + } + + if (!S) { + free(ValueDataArray); + ValueDataArray = NULL; + } + + *ValueDataSize = S; + return ValueDataArray; +} diff --git a/src/compiler-rt/lib/profile/InstrProfilingWriter.c b/src/compiler-rt/lib/profile/InstrProfilingWriter.c new file mode 100644 index 0000000000..a07bc538ed --- /dev/null +++ b/src/compiler-rt/lib/profile/InstrProfilingWriter.c @@ -0,0 +1,175 @@ +/*===- InstrProfilingWriter.c - Write instrumentation to a file or buffer -===*\ +|* +|* The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +\*===----------------------------------------------------------------------===*/ + +#include "InstrProfiling.h" +#include "InstrProfilingInternal.h" +#include + +#define INSTR_PROF_VALUE_PROF_DATA +#include "InstrProfData.inc" +void (*FreeHook)(void *) = NULL; +void* (*CallocHook)(size_t, size_t) = NULL; +uint32_t VPBufferSize = 0; + +/* The buffer writer is reponsponsible in keeping writer state + * across the call. + */ +COMPILER_RT_VISIBILITY uint32_t llvmBufferWriter(ProfDataIOVec *IOVecs, + uint32_t NumIOVecs, + void **WriterCtx) { + uint32_t I; + char **Buffer = (char **)WriterCtx; + for (I = 0; I < NumIOVecs; I++) { + size_t Length = IOVecs[I].ElmSize * IOVecs[I].NumElm; + memcpy(*Buffer, IOVecs[I].Data, Length); + *Buffer += Length; + } + return 0; +} + +static void llvmInitBufferIO(ProfBufferIO *BufferIO, WriterCallback FileWriter, + void *File, uint8_t *Buffer, uint32_t BufferSz) { + BufferIO->File = File; + BufferIO->FileWriter = FileWriter; + BufferIO->BufferStart = Buffer; + BufferIO->BufferSz = BufferSz; + BufferIO->CurOffset = 0; +} + +COMPILER_RT_VISIBILITY ProfBufferIO * +llvmCreateBufferIO(WriterCallback FileWriter, void *File, uint32_t BufferSz) { + ProfBufferIO *BufferIO = (ProfBufferIO *)CallocHook(1, sizeof(ProfBufferIO)); + uint8_t *Buffer = (uint8_t *)CallocHook(1, BufferSz); + if (!Buffer) { + FreeHook(BufferIO); + return 0; + } + llvmInitBufferIO(BufferIO, FileWriter, File, Buffer, BufferSz); + return BufferIO; +} + +COMPILER_RT_VISIBILITY void llvmDeleteBufferIO(ProfBufferIO *BufferIO) { + FreeHook(BufferIO->BufferStart); + FreeHook(BufferIO); +} + +COMPILER_RT_VISIBILITY int +llvmBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, uint32_t Size) { + /* Buffer is not large enough, it is time to flush. */ + if (Size + BufferIO->CurOffset > BufferIO->BufferSz) { + if (llvmBufferIOFlush(BufferIO) != 0) + return -1; + } + /* Special case, bypass the buffer completely. */ + ProfDataIOVec IO[] = {{Data, sizeof(uint8_t), Size}}; + if (Size > BufferIO->BufferSz) { + if (BufferIO->FileWriter(IO, 1, &BufferIO->File)) + return -1; + } else { + /* Write the data to buffer */ + uint8_t *Buffer = BufferIO->BufferStart + BufferIO->CurOffset; + llvmBufferWriter(IO, 1, (void **)&Buffer); + BufferIO->CurOffset = Buffer - BufferIO->BufferStart; + } + return 0; +} + +COMPILER_RT_VISIBILITY int llvmBufferIOFlush(ProfBufferIO *BufferIO) { + if (BufferIO->CurOffset) { + ProfDataIOVec IO[] = { + {BufferIO->BufferStart, sizeof(uint8_t), BufferIO->CurOffset}}; + if (BufferIO->FileWriter(IO, 1, &BufferIO->File)) + return -1; + BufferIO->CurOffset = 0; + } + return 0; +} + +COMPILER_RT_VISIBILITY int llvmWriteProfData(WriterCallback Writer, + void *WriterCtx, + ValueProfData **ValueDataArray, + const uint64_t ValueDataSize) { + /* Match logic in __llvm_profile_write_buffer(). */ + const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); + const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); + const uint64_t *CountersBegin = __llvm_profile_begin_counters(); + const uint64_t *CountersEnd = __llvm_profile_end_counters(); + const char *NamesBegin = __llvm_profile_begin_names(); + const char *NamesEnd = __llvm_profile_end_names(); + return llvmWriteProfDataImpl(Writer, WriterCtx, DataBegin, DataEnd, + CountersBegin, CountersEnd, ValueDataArray, + ValueDataSize, NamesBegin, NamesEnd); +} + +#define VP_BUFFER_SIZE 8 * 1024 +static int writeValueProfData(WriterCallback Writer, void *WriterCtx, + ValueProfData **ValueDataBegin, + uint64_t NumVData) { + ProfBufferIO *BufferIO; + uint32_t I = 0, BufferSz; + + if (!ValueDataBegin) + return 0; + + BufferSz = VPBufferSize ? VPBufferSize : VP_BUFFER_SIZE; + BufferIO = llvmCreateBufferIO(Writer, WriterCtx, BufferSz); + + for (I = 0; I < NumVData; I++) { + ValueProfData *CurVData = ValueDataBegin[I]; + if (!CurVData) + continue; + if (llvmBufferIOWrite(BufferIO, (const uint8_t *)CurVData, + CurVData->TotalSize) != 0) + return -1; + } + + if (llvmBufferIOFlush(BufferIO) != 0) + return -1; + llvmDeleteBufferIO(BufferIO); + + return 0; +} + +COMPILER_RT_VISIBILITY int llvmWriteProfDataImpl( + WriterCallback Writer, void *WriterCtx, + const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd, + const uint64_t *CountersBegin, const uint64_t *CountersEnd, + ValueProfData **ValueDataBegin, const uint64_t ValueDataSize, + const char *NamesBegin, const char *NamesEnd) { + + /* Calculate size of sections. */ + const uint64_t DataSize = DataEnd - DataBegin; + const uint64_t CountersSize = CountersEnd - CountersBegin; + const uint64_t NamesSize = NamesEnd - NamesBegin; + const uint64_t Padding = __llvm_profile_get_num_padding_bytes(NamesSize); + + /* Enough zeroes for padding. */ + const char Zeroes[sizeof(uint64_t)] = {0}; + + /* Create the header. */ + __llvm_profile_header Header; + + if (!DataSize) + return 0; + + /* Initialize header struture. */ +#define INSTR_PROF_RAW_HEADER(Type, Name, Init) Header.Name = Init; +#include "InstrProfData.inc" + + /* Write the data. */ + ProfDataIOVec IOVec[] = {{&Header, sizeof(__llvm_profile_header), 1}, + {DataBegin, sizeof(__llvm_profile_data), DataSize}, + {CountersBegin, sizeof(uint64_t), CountersSize}, + {NamesBegin, sizeof(uint8_t), NamesSize}, + {Zeroes, sizeof(uint8_t), Padding}}; + if (Writer(IOVec, sizeof(IOVec) / sizeof(*IOVec), &WriterCtx)) + return -1; + + return writeValueProfData(Writer, WriterCtx, ValueDataBegin, DataSize); +} diff --git a/src/compiler-rt/lib/profile/WindowsMMap.c b/src/compiler-rt/lib/profile/WindowsMMap.c new file mode 100644 index 0000000000..1f73420500 --- /dev/null +++ b/src/compiler-rt/lib/profile/WindowsMMap.c @@ -0,0 +1,128 @@ +/* + * This code is derived from uClibc (original license follows). + * https://git.uclibc.org/uClibc/tree/utils/mmap-windows.c + */ + /* mmap() replacement for Windows + * + * Author: Mike Frysinger + * Placed into the public domain + */ + +/* References: + * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx + * CloseHandle: http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx + * MapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx + * UnmapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx + */ + +#if defined(_WIN32) + +#include "WindowsMMap.h" +#include "InstrProfiling.h" + +#ifdef __USE_FILE_OFFSET64 +# define DWORD_HI(x) (x >> 32) +# define DWORD_LO(x) ((x) & 0xffffffff) +#else +# define DWORD_HI(x) (0) +# define DWORD_LO(x) (x) +#endif + +COMPILER_RT_VISIBILITY +void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) +{ + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) + return MAP_FAILED; + if (fd == -1) { + if (!(flags & MAP_ANON) || offset) + return MAP_FAILED; + } else if (flags & MAP_ANON) + return MAP_FAILED; + + DWORD flProtect; + if (prot & PROT_WRITE) { + if (prot & PROT_EXEC) + flProtect = PAGE_EXECUTE_READWRITE; + else + flProtect = PAGE_READWRITE; + } else if (prot & PROT_EXEC) { + if (prot & PROT_READ) + flProtect = PAGE_EXECUTE_READ; + else if (prot & PROT_EXEC) + flProtect = PAGE_EXECUTE; + } else + flProtect = PAGE_READONLY; + + off_t end = length + offset; + HANDLE mmap_fd, h; + if (fd == -1) + mmap_fd = INVALID_HANDLE_VALUE; + else + mmap_fd = (HANDLE)_get_osfhandle(fd); + h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); + if (h == NULL) + return MAP_FAILED; + + DWORD dwDesiredAccess; + if (prot & PROT_WRITE) + dwDesiredAccess = FILE_MAP_WRITE; + else + dwDesiredAccess = FILE_MAP_READ; + if (prot & PROT_EXEC) + dwDesiredAccess |= FILE_MAP_EXECUTE; + if (flags & MAP_PRIVATE) + dwDesiredAccess |= FILE_MAP_COPY; + void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); + if (ret == NULL) { + CloseHandle(h); + ret = MAP_FAILED; + } + return ret; +} + +COMPILER_RT_VISIBILITY +void munmap(void *addr, size_t length) +{ + UnmapViewOfFile(addr); + /* ruh-ro, we leaked handle from CreateFileMapping() ... */ +} + +COMPILER_RT_VISIBILITY +int msync(void *addr, size_t length, int flags) +{ + if (flags & MS_INVALIDATE) + return -1; /* Not supported. */ + + /* Exactly one of MS_ASYNC or MS_SYNC must be specified. */ + switch (flags & (MS_ASYNC | MS_SYNC)) { + case MS_SYNC: + case MS_ASYNC: + break; + default: + return -1; + } + + if (!FlushViewOfFile(addr, length)) + return -1; + + if (flags & MS_SYNC) { + /* FIXME: No longer have access to handle from CreateFileMapping(). */ + /* + * if (!FlushFileBuffers(h)) + * return -1; + */ + } + + return 0; +} + +COMPILER_RT_VISIBILITY +int flock(int fd, int operation) +{ + return -1; /* Not supported. */ +} + +#undef DWORD_HI +#undef DWORD_LO + +#endif /* _WIN32 */ diff --git a/src/compiler-rt/lib/profile/WindowsMMap.h b/src/compiler-rt/lib/profile/WindowsMMap.h new file mode 100644 index 0000000000..7b94eb2823 --- /dev/null +++ b/src/compiler-rt/lib/profile/WindowsMMap.h @@ -0,0 +1,65 @@ +/*===- WindowsMMap.h - Support library for PGO instrumentation ------------===*\ +|* +|* The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +\*===----------------------------------------------------------------------===*/ + +#ifndef PROFILE_INSTRPROFILING_WINDOWS_MMAP_H +#define PROFILE_INSTRPROFILING_WINDOWS_MMAP_H + +#if defined(_WIN32) + +#include +#include +#include + +/* + * mmap() flags + */ +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +/* This flag is only available in WinXP+ */ +#ifdef FILE_MAP_EXECUTE +#define PROT_EXEC 0x4 +#else +#define PROT_EXEC 0x0 +#define FILE_MAP_EXECUTE 0 +#endif + +#define MAP_FILE 0x00 +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_ANONYMOUS 0x20 +#define MAP_ANON MAP_ANONYMOUS +#define MAP_FAILED ((void *) -1) + +/* + * msync() flags + */ +#define MS_ASYNC 0x0001 /* return immediately */ +#define MS_INVALIDATE 0x0002 /* invalidate all cached data */ +#define MS_SYNC 0x0010 /* msync synchronously */ + +/* + * flock() operations + */ +#define LOCK_SH 1 /* shared lock */ +#define LOCK_EX 2 /* exclusive lock */ +#define LOCK_NB 4 /* don't block when locking */ +#define LOCK_UN 8 /* unlock */ + +void *mmap(void *start, size_t length, int prot, int flags, int fd, + off_t offset); + +void munmap(void *addr, size_t length); + +int msync(void *addr, size_t length, int flags); + +int flock(int fd, int operation); + +#endif /* _WIN32 */ + +#endif /* PROFILE_INSTRPROFILING_WINDOWS_MMAP_H */ diff --git a/src/compiler-rt/lib/safestack/.clang-format b/src/compiler-rt/lib/safestack/.clang-format new file mode 100644 index 0000000000..f6cb8ad931 --- /dev/null +++ b/src/compiler-rt/lib/safestack/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: Google diff --git a/src/compiler-rt/lib/safestack/safestack.cc b/src/compiler-rt/lib/safestack/safestack.cc index 5254462d92..92c24b35d6 100644 --- a/src/compiler-rt/lib/safestack/safestack.cc +++ b/src/compiler-rt/lib/safestack/safestack.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,9 @@ const unsigned kStackAlign = 16; /// size rlimit is set to infinity. const unsigned kDefaultUnsafeStackSize = 0x2800000; +/// Runtime page size obtained through sysconf +static unsigned pageSize; + // TODO: To make accessing the unsafe stack pointer faster, we plan to // eventually store it directly in the thread control block data structure on // platforms where this structure is pointed to by %fs or %gs. This is exactly @@ -185,7 +189,7 @@ INTERCEPTOR(int, pthread_create, pthread_t *thread, CHECK_NE(size, 0); CHECK_EQ((size & (kStackAlign - 1)), 0); - CHECK_EQ((guard & (PAGE_SIZE - 1)), 0); + CHECK_EQ((guard & (pageSize - 1)), 0); void *addr = unsafe_stack_alloc(size, guard); struct tinfo *tinfo = @@ -217,6 +221,7 @@ void __safestack_init() { void *addr = unsafe_stack_alloc(size, guard); unsafe_stack_setup(addr, size, guard); + pageSize = sysconf(_SC_PAGESIZE); // Initialize pthread interceptors for thread allocation INTERCEPT_FUNCTION(pthread_create); diff --git a/src/compiler-rt/lib/sanitizer_common/.clang-format b/src/compiler-rt/lib/sanitizer_common/.clang-format new file mode 100644 index 0000000000..f6cb8ad931 --- /dev/null +++ b/src/compiler-rt/lib/sanitizer_common/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: Google diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_asm.h b/src/compiler-rt/lib/sanitizer_common/sanitizer_asm.h index 906012a96f..47c2b12a20 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_asm.h +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_asm.h @@ -23,8 +23,11 @@ # define CFI_STARTPROC .cfi_startproc # define CFI_ENDPROC .cfi_endproc # define CFI_ADJUST_CFA_OFFSET(n) .cfi_adjust_cfa_offset n +# define CFI_DEF_CFA_OFFSET(n) .cfi_def_cfa_offset n # define CFI_REL_OFFSET(reg, n) .cfi_rel_offset reg, n +# define CFI_OFFSET(reg, n) .cfi_offset reg, n # define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg +# define CFI_DEF_CFA(reg, n) .cfi_def_cfa reg, n # define CFI_RESTORE(reg) .cfi_restore reg #else // No CFI @@ -32,9 +35,24 @@ # define CFI_STARTPROC # define CFI_ENDPROC # define CFI_ADJUST_CFA_OFFSET(n) +# define CFI_DEF_CFA_OFFSET(n) # define CFI_REL_OFFSET(reg, n) +# define CFI_OFFSET(reg, n) # define CFI_DEF_CFA_REGISTER(reg) +# define CFI_DEF_CFA(reg, n) # define CFI_RESTORE(reg) #endif - +#if !defined(__APPLE__) +# define ASM_HIDDEN(symbol) .hidden symbol +# define ASM_TYPE_FUNCTION(symbol) .type symbol, @function +# define ASM_SIZE(symbol) .size symbol, .-symbol +# define ASM_TSAN_SYMBOL(symbol) symbol +# define ASM_TSAN_SYMBOL_INTERCEPTOR(symbol) symbol +#else +# define ASM_HIDDEN(symbol) +# define ASM_TYPE_FUNCTION(symbol) +# define ASM_SIZE(symbol) +# define ASM_TSAN_SYMBOL(symbol) _##symbol +# define ASM_TSAN_SYMBOL_INTERCEPTOR(symbol) _wrap_##symbol +#endif diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_common.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_common.cc index b40a457c0b..9b41a3aa0a 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_common.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_common.cc @@ -164,11 +164,12 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond, } void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, - const char *mmap_type, error_t err) { + const char *mmap_type, error_t err, + bool raw_report) { static int recursion_count; - if (recursion_count) { + if (raw_report || recursion_count) { + // If raw report is requested or we went into recursion, just die. // The Report() and CHECK calls below may call mmap recursively and fail. - // If we went into recursion, just die. RawWrite("ERROR: Failed to mmap\n"); Die(); } @@ -176,7 +177,9 @@ void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, Report("ERROR: %s failed to " "%s 0x%zx (%zd) bytes of %s (error code: %d)\n", SanitizerToolName, mmap_type, size, size, mem_type, err); +#ifndef SANITIZER_GO DumpProcessMap(); +#endif UNREACHABLE("unable to mmap"); } @@ -295,6 +298,40 @@ void ReportErrorSummary(const char *error_type, const AddressInfo &info) { } #endif +// Removes the ANSI escape sequences from the input string (in-place). +void RemoveANSIEscapeSequencesFromString(char *str) { + if (!str) + return; + + // We are going to remove the escape sequences in place. + char *s = str; + char *z = str; + while (*s != '\0') { + CHECK_GE(s, z); + // Skip over ANSI escape sequences with pointer 's'. + if (*s == '\033' && *(s + 1) == '[') { + s = internal_strchrnul(s, 'm'); + if (*s == '\0') { + break; + } + s++; + continue; + } + // 's' now points at a character we want to keep. Copy over the buffer + // content if the escape sequence has been perviously skipped andadvance + // both pointers. + if (s != z) + *z = *s; + + // If we have not seen an escape sequence, just advance both pointers. + z++; + s++; + } + + // Null terminate the string. + *z = '\0'; +} + void LoadedModule::set(const char *module_name, uptr base_address) { clear(); full_name_ = internal_strdup(module_name); diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/src/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 43cd2d0e8c..7e80507ba0 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -49,6 +49,8 @@ static const uptr kMaxNumberOfModules = 1 << 14; const uptr kMaxThreadStackSize = 1 << 30; // 1Gb +static const uptr kErrorMessageBufferSize = 1 << 16; + // Denotes fake PC values that come from JIT/JAVA/etc. // For such PC values __tsan_symbolize_external() will be called. const u64 kExternalPCBit = 1ULL << 60; @@ -76,7 +78,10 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, uptr *tls_addr, uptr *tls_size); // Memory management -void *MmapOrDie(uptr size, const char *mem_type); +void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false); +INLINE void *MmapOrDieQuietly(uptr size, const char *mem_type) { + return MmapOrDie(size, mem_type, /*raw_report*/ true); +} void UnmapOrDie(void *addr, uptr size); void *MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr); @@ -162,6 +167,7 @@ void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback); // IO void RawWrite(const char *buffer); bool ColorizeReports(); +void RemoveANSIEscapeSequencesFromString(char *buffer); void Printf(const char *format, ...); void Report(const char *format, ...); void SetPrintfAndReportCallback(void (*callback)(const char *)); @@ -309,7 +315,8 @@ void NORETURN Die(); void NORETURN CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2); void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, - const char *mmap_type, error_t err); + const char *mmap_type, error_t err, + bool raw_report = false); // Set the name of the current thread to 'name', return true on succees. // The name may be truncated to a system-dependent limit. @@ -422,7 +429,7 @@ INLINE uptr RoundUpToPowerOfTwo(uptr size) { } INLINE uptr RoundUpTo(uptr size, uptr boundary) { - CHECK(IsPowerOfTwo(boundary)); + RAW_CHECK(IsPowerOfTwo(boundary)); return (size + boundary - 1) & ~(boundary - 1); } @@ -648,22 +655,34 @@ enum AndroidApiLevel { ANDROID_POST_LOLLIPOP = 23 }; +void WriteToSyslog(const char *buffer); + +#if SANITIZER_MAC +void LogFullErrorReport(const char *buffer); +#else +INLINE void LogFullErrorReport(const char *buffer) {} +#endif + +#if SANITIZER_LINUX || SANITIZER_MAC +void WriteOneLineToSyslog(const char *s); +void LogMessageOnPrintf(const char *str); +#else +INLINE void WriteOneLineToSyslog(const char *s) {} +INLINE void LogMessageOnPrintf(const char *str) {} +#endif + #if SANITIZER_LINUX // Initialize Android logging. Any writes before this are silently lost. void AndroidLogInit(); -void WriteToSyslog(const char *buffer); #else INLINE void AndroidLogInit() {} -INLINE void WriteToSyslog(const char *buffer) {} #endif #if SANITIZER_ANDROID -void GetExtraActivationFlags(char *buf, uptr size); void SanitizerInitializeUnwinder(); AndroidApiLevel AndroidGetApiLevel(); #else INLINE void AndroidLogWrite(const char *buffer_unused) {} -INLINE void GetExtraActivationFlags(char *buf, uptr size) { *buf = '\0'; } INLINE void SanitizerInitializeUnwinder() {} INLINE AndroidApiLevel AndroidGetApiLevel() { return ANDROID_NOT_ANDROID; } #endif @@ -712,6 +731,9 @@ struct SignalContext { void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp); +void DisableReexec(); +void MaybeReexec(); + } // namespace __sanitizer inline void *operator new(__sanitizer::operator_new_size_type size, diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/src/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 62902a306c..2a748cdc68 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -214,13 +214,11 @@ static inline int CharCmpX(unsigned char c1, unsigned char c2) { } DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, uptr called_pc, - const char *s1, const char *s2) + const char *s1, const char *s2, int result) INTERCEPTOR(int, strcmp, const char *s1, const char *s2) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, strcmp, s1, s2); - CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1, - s2); unsigned char c1, c2; uptr i; for (i = 0;; i++) { @@ -230,19 +228,21 @@ INTERCEPTOR(int, strcmp, const char *s1, const char *s2) { } COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1); COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1); - return CharCmpX(c1, c2); + int result = CharCmpX(c1, c2); + CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1, + s2, result); + return result; } DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, uptr called_pc, - const char *s1, const char *s2, uptr n) + const char *s1, const char *s2, uptr n, + int result) INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) { if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) return internal_strncmp(s1, s2, size); void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size); - CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1, - s2, size); unsigned char c1 = 0, c2 = 0; uptr i; for (i = 0; i < size; i++) { @@ -252,7 +252,10 @@ INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) { } COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size)); COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size)); - return CharCmpX(c1, c2); + int result = CharCmpX(c1, c2); + CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1, + s2, size, result); + return result; } #define INIT_STRCMP COMMON_INTERCEPT_FUNCTION(strcmp) @@ -400,15 +403,14 @@ INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) { #if SANITIZER_INTERCEPT_MEMCMP DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, uptr called_pc, - const void *s1, const void *s2, uptr n) + const void *s1, const void *s2, uptr n, + int result) INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { - void *ctx; - COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size); if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) return internal_memcmp(a1, a2, size); - CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1, - a2, size); + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size); if (common_flags()->intercept_memcmp) { if (common_flags()->strict_memcmp) { // Check the entire regions even if the first bytes of the buffers are @@ -428,10 +430,16 @@ INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { } COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size)); COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size)); - return CharCmpX(c1, c2); + int r = CharCmpX(c1, c2); + CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), + a1, a2, size, r); + return r; } } - return REAL(memcmp(a1, a2, size)); + int result = REAL(memcmp(a1, a2, size)); + CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1, + a2, size, result); + return result; } #define INIT_MEMCMP COMMON_INTERCEPT_FUNCTION(memcmp) @@ -490,7 +498,7 @@ INTERCEPTOR(float, frexpf, float x, int *exp) { COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. float res = REAL(frexpf)(x, exp); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp)); return res; @@ -501,7 +509,7 @@ INTERCEPTOR(long double, frexpl, long double x, int *exp) { COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. long double res = REAL(frexpl)(x, exp); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp)); return res; @@ -542,7 +550,7 @@ INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) { COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SSIZE_T res = REAL(read)(fd, ptr, count); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); @@ -560,7 +568,7 @@ INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) { COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SSIZE_T res = REAL(pread)(fd, ptr, count, offset); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); @@ -578,7 +586,7 @@ INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) { COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SSIZE_T res = REAL(pread64)(fd, ptr, count, offset); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); @@ -825,7 +833,7 @@ INTERCEPTOR(char *, ctime, unsigned long *timep) { COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *res = REAL(ctime)(timep); if (res) { COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); @@ -838,7 +846,7 @@ INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) { COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *res = REAL(ctime_r)(timep, result); if (res) { COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); @@ -851,7 +859,7 @@ INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) { COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *res = REAL(asctime)(tm); if (res) { COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm)); @@ -864,7 +872,7 @@ INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) { COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *res = REAL(asctime_r)(tm, result); if (res) { COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm)); @@ -908,7 +916,7 @@ INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) { COMMON_INTERCEPTOR_READ_RANGE(ctx, format, REAL(strlen)(format) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *res = REAL(strptime)(s, format, tm); COMMON_INTERCEPTOR_READ_STRING(ctx, s, res ? res - s : 0); if (res && tm) { @@ -1045,7 +1053,7 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format) // FIXME: under ASan the REAL() call below may write to freed memory and // corrupt its metadata. See -// https://code.google.com/p/address-sanitizer/issues/detail?id=321. +// https://github.com/google/sanitizers/issues/321. #define VSPRINTF_INTERCEPTOR_IMPL(vname, str, ...) \ { \ VPRINTF_INTERCEPTOR_ENTER(vname, str, __VA_ARGS__) \ @@ -1062,7 +1070,7 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format) // FIXME: under ASan the REAL() call below may write to freed memory and // corrupt its metadata. See -// https://code.google.com/p/address-sanitizer/issues/detail?id=321. +// https://github.com/google/sanitizers/issues/321. #define VSNPRINTF_INTERCEPTOR_IMPL(vname, str, size, ...) \ { \ VPRINTF_INTERCEPTOR_ENTER(vname, str, size, __VA_ARGS__) \ @@ -1079,7 +1087,7 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format) // FIXME: under ASan the REAL() call below may write to freed memory and // corrupt its metadata. See -// https://code.google.com/p/address-sanitizer/issues/detail?id=321. +// https://github.com/google/sanitizers/issues/321. #define VASPRINTF_INTERCEPTOR_IMPL(vname, strp, ...) \ { \ VPRINTF_INTERCEPTOR_ENTER(vname, strp, __VA_ARGS__) \ @@ -1364,7 +1372,7 @@ INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd, COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result); if (!res) { if (result && *result) unpoison_passwd(ctx, *result); @@ -1379,7 +1387,7 @@ INTERCEPTOR(int, getpwuid_r, u32 uid, __sanitizer_passwd *pwd, char *buf, COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result); if (!res) { if (result && *result) unpoison_passwd(ctx, *result); @@ -1395,7 +1403,7 @@ INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp, COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getgrnam_r)(name, grp, buf, buflen, result); if (!res) { if (result && *result) unpoison_group(ctx, *result); @@ -1410,7 +1418,7 @@ INTERCEPTOR(int, getgrgid_r, u32 gid, __sanitizer_group *grp, char *buf, COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result); if (!res) { if (result && *result) unpoison_group(ctx, *result); @@ -1479,7 +1487,7 @@ INTERCEPTOR(int, getpwent_r, __sanitizer_passwd *pwbuf, char *buf, COMMON_INTERCEPTOR_ENTER(ctx, getpwent_r, pwbuf, buf, buflen, pwbufp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getpwent_r)(pwbuf, buf, buflen, pwbufp); if (!res) { if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp); @@ -1494,7 +1502,7 @@ INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf, COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp); if (!res) { if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp); @@ -1509,7 +1517,7 @@ INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen, COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp); if (!res) { if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp); @@ -1524,7 +1532,7 @@ INTERCEPTOR(int, fgetgrent_r, void *fp, __sanitizer_group *pwbuf, char *buf, COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(fgetgrent_r)(fp, pwbuf, buf, buflen, pwbufp); if (!res) { if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp); @@ -1581,7 +1589,7 @@ INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) { COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(clock_getres)(clk_id, tp); if (!res && tp) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz); @@ -1593,7 +1601,7 @@ INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) { COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(clock_gettime)(clk_id, tp); if (!res) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz); @@ -1620,7 +1628,7 @@ INTERCEPTOR(int, getitimer, int which, void *curr_value) { COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getitimer)(which, curr_value); if (!res && curr_value) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz); @@ -1634,7 +1642,7 @@ INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) { COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerval_sz); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(setitimer)(which, new_value, old_value); if (!res && old_value) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz); @@ -1691,16 +1699,19 @@ static int wrapped_gl_stat(const char *s, void *st) { return pglob_copy->gl_stat(s, st); } +static const __sanitizer_glob_t kGlobCopy = { + 0, 0, 0, + 0, wrapped_gl_closedir, wrapped_gl_readdir, + wrapped_gl_opendir, wrapped_gl_lstat, wrapped_gl_stat}; + INTERCEPTOR(int, glob, const char *pattern, int flags, int (*errfunc)(const char *epath, int eerrno), __sanitizer_glob_t *pglob) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob); COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0); - __sanitizer_glob_t glob_copy = { - 0, 0, 0, - 0, wrapped_gl_closedir, wrapped_gl_readdir, - wrapped_gl_opendir, wrapped_gl_lstat, wrapped_gl_stat}; + __sanitizer_glob_t glob_copy; + internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy)); if (flags & glob_altdirfunc) { Swap(pglob->gl_closedir, glob_copy.gl_closedir); Swap(pglob->gl_readdir, glob_copy.gl_readdir); @@ -1728,10 +1739,8 @@ INTERCEPTOR(int, glob64, const char *pattern, int flags, void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob); COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0); - __sanitizer_glob_t glob_copy = { - 0, 0, 0, - 0, wrapped_gl_closedir, wrapped_gl_readdir, - wrapped_gl_opendir, wrapped_gl_lstat, wrapped_gl_stat}; + __sanitizer_glob_t glob_copy; + internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy)); if (flags & glob_altdirfunc) { Swap(pglob->gl_closedir, glob_copy.gl_closedir); Swap(pglob->gl_readdir, glob_copy.gl_readdir); @@ -1768,7 +1777,7 @@ INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) { COMMON_INTERCEPTOR_ENTER(ctx, wait, status); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(wait)(status); if (res != -1 && status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); @@ -1786,7 +1795,7 @@ INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop, COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(waitid)(idtype, id, infop, options); if (res != -1 && infop) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz); @@ -1797,7 +1806,7 @@ INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) { COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(waitpid)(pid, status, options); if (res != -1 && status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); @@ -1808,7 +1817,7 @@ INTERCEPTOR(int, wait3, int *status, int options, void *rusage) { COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(wait3)(status, options, rusage); if (res != -1) { if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); @@ -1822,7 +1831,7 @@ INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) { COMMON_INTERCEPTOR_ENTER(ctx, __wait4, pid, status, options, rusage); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(__wait4)(pid, status, options, rusage); if (res != -1) { if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); @@ -1837,7 +1846,7 @@ INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) { COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(wait4)(pid, status, options, rusage); if (res != -1) { if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); @@ -1866,7 +1875,7 @@ INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) { // FIXME: figure out read size based on the address family. // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *res = REAL(inet_ntop)(af, src, dst, size); if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); return res; @@ -1878,7 +1887,7 @@ INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) { // FIXME: figure out read size based on the address family. // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(inet_pton)(af, src, dst); if (res == 1) { uptr sz = __sanitizer_in_addr_sz(af); @@ -1900,7 +1909,7 @@ INTERCEPTOR(int, inet_aton, const char *cp, void *dst) { if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(inet_aton)(cp, dst); if (res != 0) { uptr sz = __sanitizer_in_addr_sz(af_inet); @@ -1919,7 +1928,7 @@ INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) { COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(pthread_getschedparam)(thread, policy, param); if (res == 0) { if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy)); @@ -1946,7 +1955,7 @@ INTERCEPTOR(int, getaddrinfo, char *node, char *service, COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo)); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getaddrinfo)(node, service, hints, out); if (res == 0 && out) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out)); @@ -1978,7 +1987,7 @@ INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host, // There is padding in in_addr that may make this too noisy // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags); if (res == 0) { @@ -2002,7 +2011,7 @@ INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) { int addrlen_in = *addrlen; // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getsockname)(sock_fd, addr, addrlen); if (res == 0) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen)); @@ -2088,7 +2097,7 @@ INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret, h_errnop); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop); if (result) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); @@ -2111,7 +2120,7 @@ INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf, h_errnop); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop); if (result) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); @@ -2137,7 +2146,7 @@ INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type, COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result, h_errnop); if (result) { @@ -2163,7 +2172,7 @@ INTERCEPTOR(int, gethostbyname2_r, char *name, int af, result, h_errnop); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop); if (result) { @@ -2189,7 +2198,7 @@ INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval, if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen)); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen); if (res == 0) if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen); @@ -2233,7 +2242,7 @@ INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) { } // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int fd2 = REAL(accept4)(fd, addr, addrlen, f); if (fd2 >= 0) { if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2); @@ -2253,7 +2262,7 @@ INTERCEPTOR(double, modf, double x, double *iptr) { COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. double res = REAL(modf)(x, iptr); if (iptr) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr)); @@ -2265,7 +2274,7 @@ INTERCEPTOR(float, modff, float x, float *iptr) { COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. float res = REAL(modff)(x, iptr); if (iptr) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr)); @@ -2277,7 +2286,7 @@ INTERCEPTOR(long double, modfl, long double x, long double *iptr) { COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. long double res = REAL(modfl)(x, iptr); if (iptr) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr)); @@ -2312,7 +2321,7 @@ INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg, COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SSIZE_T res = REAL(recvmsg)(fd, msg, flags); if (res >= 0) { if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); @@ -2336,7 +2345,7 @@ INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) { if (addrlen) addr_sz = *addrlen; // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getpeername)(sockfd, addr, addrlen); if (!res && addr && addrlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen)); @@ -2352,7 +2361,7 @@ INTERCEPTOR(int, sysinfo, void *info) { void *ctx; // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info); int res = REAL(sysinfo)(info); if (!res && info) @@ -2380,7 +2389,7 @@ INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) { COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. __sanitizer_dirent *res = REAL(readdir)(dirp); if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen); return res; @@ -2392,7 +2401,7 @@ INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry, COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(readdir_r)(dirp, entry, result); if (!res) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); @@ -2416,7 +2425,7 @@ INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) { COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. __sanitizer_dirent64 *res = REAL(readdir64)(dirp); if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen); return res; @@ -2428,7 +2437,7 @@ INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry, COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(readdir64_r)(dirp, entry, result); if (!res) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); @@ -2475,7 +2484,7 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. uptr res = REAL(ptrace)(request, pid, addr, data); if (!res && data) { @@ -2530,7 +2539,7 @@ INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) { COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *res = REAL(getcwd)(buf, size); if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); return res; @@ -2546,7 +2555,7 @@ INTERCEPTOR(char *, get_current_dir_name, int fake) { COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name, fake); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *res = REAL(get_current_dir_name)(fake); if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); return res; @@ -2595,7 +2604,7 @@ INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) { COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *real_endptr; INTMAX_T res = REAL(strtoimax)(nptr, &real_endptr, base); StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); @@ -2607,7 +2616,7 @@ INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) { COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *real_endptr; INTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base); StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); @@ -2627,7 +2636,7 @@ INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) { COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SIZE_T res = REAL(mbstowcs)(dest, src, len); if (res != (SIZE_T) - 1 && dest) { SIZE_T write_cnt = res + (res < len); @@ -2644,7 +2653,7 @@ INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len, if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps); if (res != (SIZE_T)(-1) && dest && src) { // This function, and several others, may or may not write the terminating @@ -2674,7 +2683,7 @@ INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms, if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps); if (res != (SIZE_T)(-1) && dest && src) { SIZE_T write_cnt = res + !*src; @@ -2694,7 +2703,7 @@ INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) { COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SIZE_T res = REAL(wcstombs)(dest, src, len); if (res != (SIZE_T) - 1 && dest) { SIZE_T write_cnt = res + (res < len); @@ -2711,7 +2720,7 @@ INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len, if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps); if (res != (SIZE_T) - 1 && dest && src) { SIZE_T write_cnt = res + !*src; @@ -2739,7 +2748,7 @@ INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms, if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps); if (res != ((SIZE_T)-1) && dest && src) { SIZE_T write_cnt = res + !*src; @@ -2761,7 +2770,7 @@ INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) { if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SIZE_T res = REAL(wcrtomb)(dest, src, ps); if (res != ((SIZE_T)-1) && dest) { SIZE_T write_cnt = res; @@ -2781,7 +2790,7 @@ INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) { COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(tcgetattr)(fd, termios_p); if (!res && termios_p) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz); @@ -2838,7 +2847,7 @@ INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) { COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SIZE_T res = REAL(confstr)(name, buf, len); if (buf && res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len); @@ -2855,7 +2864,7 @@ INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) { COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(sched_getaffinity)(pid, cpusetsize, mask); if (mask && !res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize); return res; @@ -2897,7 +2906,7 @@ INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) { COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *res = REAL(strerror_r)(errnum, buf, buflen); // There are 2 versions of strerror_r: // * POSIX version returns 0 on success, negative error code on failure, @@ -2928,7 +2937,7 @@ INTERCEPTOR(int, __xpg_strerror_r, int errnum, char *buf, SIZE_T buflen) { COMMON_INTERCEPTOR_ENTER(ctx, __xpg_strerror_r, errnum, buf, buflen); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(__xpg_strerror_r)(errnum, buf, buflen); // This version always returns a null-terminated string. if (buf && buflen) @@ -2973,7 +2982,7 @@ INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist, scandir_compar = compar; // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(scandir)(dirp, namelist, filter ? wrapped_scandir_filter : nullptr, compar ? wrapped_scandir_compar : nullptr); @@ -3026,7 +3035,7 @@ INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist, scandir64_compar = compar; // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(scandir64)(dirp, namelist, filter ? wrapped_scandir64_filter : nullptr, @@ -3053,7 +3062,7 @@ INTERCEPTOR(int, getgroups, int size, u32 *lst) { COMMON_INTERCEPTOR_ENTER(ctx, getgroups, size, lst); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getgroups)(size, lst); if (res && lst) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst)); return res; @@ -3119,7 +3128,7 @@ INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) { if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(wordexp)(s, p, flags); if (!res && p) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); @@ -3145,7 +3154,7 @@ INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) { // FIXME: read sigset_t when all of sigemptyset, etc are intercepted // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(sigwait)(set, sig); if (!res && sig) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sig, sizeof(*sig)); return res; @@ -3162,7 +3171,7 @@ INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) { // FIXME: read sigset_t when all of sigemptyset, etc are intercepted // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(sigwaitinfo)(set, info); if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz); return res; @@ -3181,7 +3190,7 @@ INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info, // FIXME: read sigset_t when all of sigemptyset, etc are intercepted // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(sigtimedwait)(set, info, timeout); if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz); return res; @@ -3197,7 +3206,7 @@ INTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) { COMMON_INTERCEPTOR_ENTER(ctx, sigemptyset, set); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(sigemptyset)(set); if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set)); return res; @@ -3208,7 +3217,7 @@ INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) { COMMON_INTERCEPTOR_ENTER(ctx, sigfillset, set); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(sigfillset)(set); if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set)); return res; @@ -3226,7 +3235,7 @@ INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) { COMMON_INTERCEPTOR_ENTER(ctx, sigpending, set); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(sigpending)(set); if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set)); return res; @@ -3244,7 +3253,7 @@ INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set, // FIXME: read sigset_t when all of sigemptyset, etc are intercepted // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(sigprocmask)(how, set, oldset); if (!res && oldset) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset)); @@ -3261,7 +3270,7 @@ INTERCEPTOR(int, backtrace, void **buffer, int size) { COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(backtrace)(buffer, size); if (res && buffer) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buffer, res * sizeof(*buffer)); @@ -3275,7 +3284,7 @@ INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) { COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer)); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char **res = REAL(backtrace_symbols)(buffer, size); if (res && size) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res)); @@ -3383,7 +3392,7 @@ INTERCEPTOR(int, statfs, char *path, void *buf) { if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(statfs)(path, buf); if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz); return res; @@ -3393,7 +3402,7 @@ INTERCEPTOR(int, fstatfs, int fd, void *buf) { COMMON_INTERCEPTOR_ENTER(ctx, fstatfs, fd, buf); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(fstatfs)(fd, buf); if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz); return res; @@ -3412,7 +3421,7 @@ INTERCEPTOR(int, statfs64, char *path, void *buf) { if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(statfs64)(path, buf); if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz); return res; @@ -3422,7 +3431,7 @@ INTERCEPTOR(int, fstatfs64, int fd, void *buf) { COMMON_INTERCEPTOR_ENTER(ctx, fstatfs64, fd, buf); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(fstatfs64)(fd, buf); if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz); return res; @@ -3441,7 +3450,7 @@ INTERCEPTOR(int, statvfs, char *path, void *buf) { if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(statvfs)(path, buf); if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz); return res; @@ -3451,7 +3460,7 @@ INTERCEPTOR(int, fstatvfs, int fd, void *buf) { COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(fstatvfs)(fd, buf); if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz); return res; @@ -3470,7 +3479,7 @@ INTERCEPTOR(int, statvfs64, char *path, void *buf) { if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(statvfs64)(path, buf); if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz); return res; @@ -3480,7 +3489,7 @@ INTERCEPTOR(int, fstatvfs64, int fd, void *buf) { COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs64, fd, buf); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(fstatvfs64)(fd, buf); if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz); return res; @@ -3536,7 +3545,7 @@ INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) { if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr)); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(ether_ntohost)(hostname, addr); if (!res && hostname) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1); @@ -3549,7 +3558,7 @@ INTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) { COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(ether_hostton)(hostname, addr); if (!res && addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr)); return res; @@ -3561,7 +3570,7 @@ INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr, if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, REAL(strlen)(line) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(ether_line)(line, addr, hostname); if (!res) { if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr)); @@ -3585,7 +3594,7 @@ INTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) { if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr)); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *res = REAL(ether_ntoa_r)(addr, buf); if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); return res; @@ -3597,7 +3606,7 @@ INTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf, if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. __sanitizer_ether_addr *res = REAL(ether_aton_r)(buf, addr); if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(*res)); return res; @@ -3615,7 +3624,7 @@ INTERCEPTOR(int, shmctl, int shmid, int cmd, void *buf) { COMMON_INTERCEPTOR_ENTER(ctx, shmctl, shmid, cmd, buf); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(shmctl)(shmid, cmd, buf); if (res >= 0) { unsigned sz = 0; @@ -3640,7 +3649,7 @@ INTERCEPTOR(int, random_r, void *buf, u32 *result) { COMMON_INTERCEPTOR_ENTER(ctx, random_r, buf, result); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(random_r)(buf, result); if (!res && result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); @@ -3653,7 +3662,7 @@ INTERCEPTOR(int, random_r, void *buf, u32 *result) { // FIXME: under ASan the REAL() call below may write to freed memory and corrupt // its metadata. See -// https://code.google.com/p/address-sanitizer/issues/detail?id=321. +// https://github.com/google/sanitizers/issues/321. #if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET || \ SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSSCHED || \ SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GET || \ @@ -3692,7 +3701,7 @@ INTERCEPTOR(int, pthread_attr_getstack, void *attr, void **addr, SIZE_T *size) { COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getstack, attr, addr, size); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(pthread_attr_getstack)(attr, addr, size); if (!res) { if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr)); @@ -3741,7 +3750,7 @@ INTERCEPTOR(int, pthread_attr_getaffinity_np, void *attr, SIZE_T cpusetsize, cpuset); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(pthread_attr_getaffinity_np)(attr, cpusetsize, cpuset); if (!res && cpusetsize && cpuset) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize); @@ -3851,7 +3860,7 @@ INTERCEPTOR(char *, tmpnam, char *s) { if (s) // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1); else COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); @@ -3869,7 +3878,7 @@ INTERCEPTOR(char *, tmpnam_r, char *s) { COMMON_INTERCEPTOR_ENTER(ctx, tmpnam_r, s); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *res = REAL(tmpnam_r)(s); if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1); return res; @@ -3913,7 +3922,7 @@ INTERCEPTOR(void, sincos, double x, double *sin, double *cos) { COMMON_INTERCEPTOR_ENTER(ctx, sincos, x, sin, cos); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. REAL(sincos)(x, sin, cos); if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin)); if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos)); @@ -3923,7 +3932,7 @@ INTERCEPTOR(void, sincosf, float x, float *sin, float *cos) { COMMON_INTERCEPTOR_ENTER(ctx, sincosf, x, sin, cos); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. REAL(sincosf)(x, sin, cos); if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin)); if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos)); @@ -3933,7 +3942,7 @@ INTERCEPTOR(void, sincosl, long double x, long double *sin, long double *cos) { COMMON_INTERCEPTOR_ENTER(ctx, sincosl, x, sin, cos); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. REAL(sincosl)(x, sin, cos); if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin)); if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos)); @@ -3952,7 +3961,7 @@ INTERCEPTOR(double, remquo, double x, double y, int *quo) { COMMON_INTERCEPTOR_ENTER(ctx, remquo, x, y, quo); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. double res = REAL(remquo)(x, y, quo); if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo)); return res; @@ -3962,7 +3971,7 @@ INTERCEPTOR(float, remquof, float x, float y, int *quo) { COMMON_INTERCEPTOR_ENTER(ctx, remquof, x, y, quo); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. float res = REAL(remquof)(x, y, quo); if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo)); return res; @@ -3972,7 +3981,7 @@ INTERCEPTOR(long double, remquol, long double x, long double y, int *quo) { COMMON_INTERCEPTOR_ENTER(ctx, remquol, x, y, quo); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. long double res = REAL(remquol)(x, y, quo); if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo)); return res; @@ -4022,7 +4031,7 @@ INTERCEPTOR(double, lgamma_r, double x, int *signp) { COMMON_INTERCEPTOR_ENTER(ctx, lgamma_r, x, signp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. double res = REAL(lgamma_r)(x, signp); if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp)); return res; @@ -4032,7 +4041,7 @@ INTERCEPTOR(float, lgammaf_r, float x, int *signp) { COMMON_INTERCEPTOR_ENTER(ctx, lgammaf_r, x, signp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. float res = REAL(lgammaf_r)(x, signp); if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp)); return res; @@ -4050,7 +4059,7 @@ INTERCEPTOR(long double, lgammal_r, long double x, int *signp) { COMMON_INTERCEPTOR_ENTER(ctx, lgammal_r, x, signp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. long double res = REAL(lgammal_r)(x, signp); if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp)); return res; @@ -4066,7 +4075,7 @@ INTERCEPTOR(int, drand48_r, void *buffer, double *result) { COMMON_INTERCEPTOR_ENTER(ctx, drand48_r, buffer, result); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(drand48_r)(buffer, result); if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); return res; @@ -4076,7 +4085,7 @@ INTERCEPTOR(int, lrand48_r, void *buffer, long *result) { COMMON_INTERCEPTOR_ENTER(ctx, lrand48_r, buffer, result); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(lrand48_r)(buffer, result); if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); return res; @@ -4106,7 +4115,7 @@ INTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) { COMMON_INTERCEPTOR_ENTER(ctx, getline, lineptr, n, stream); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SSIZE_T res = REAL(getline)(lineptr, n, stream); if (res > 0) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr)); @@ -4118,7 +4127,7 @@ INTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) { // FIXME: under ASan the call below may write to freed memory and corrupt its // metadata. See -// https://code.google.com/p/address-sanitizer/issues/detail?id=321. +// https://github.com/google/sanitizers/issues/321. #define GETDELIM_INTERCEPTOR_IMPL(vname) \ { \ void *ctx; \ @@ -4165,7 +4174,7 @@ INTERCEPTOR(SIZE_T, iconv, void *cd, char **inbuf, SIZE_T *inbytesleft, void *outbuf_orig = outbuf ? *outbuf : nullptr; // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SIZE_T res = REAL(iconv)(cd, inbuf, inbytesleft, outbuf, outbytesleft); if (res != (SIZE_T) - 1 && outbuf && *outbuf > outbuf_orig) { SIZE_T sz = (char *)*outbuf - (char *)outbuf_orig; @@ -4184,7 +4193,7 @@ INTERCEPTOR(__sanitizer_clock_t, times, void *tms) { COMMON_INTERCEPTOR_ENTER(ctx, times, tms); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. __sanitizer_clock_t res = REAL(times)(tms); if (res != (__sanitizer_clock_t)-1 && tms) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tms, struct_tms_sz); @@ -4227,7 +4236,7 @@ INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) { if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SSIZE_T res = REAL(listxattr)(path, list, size); // Here and below, size == 0 is a special case where nothing is written to the // buffer, and res contains the desired buffer size. @@ -4240,7 +4249,7 @@ INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) { if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SSIZE_T res = REAL(llistxattr)(path, list, size); if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res); return res; @@ -4250,7 +4259,7 @@ INTERCEPTOR(SSIZE_T, flistxattr, int fd, char *list, SIZE_T size) { COMMON_INTERCEPTOR_ENTER(ctx, flistxattr, fd, list, size); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SSIZE_T res = REAL(flistxattr)(fd, list, size); if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res); return res; @@ -4272,7 +4281,7 @@ INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value, if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SSIZE_T res = REAL(getxattr)(path, name, value, size); if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res); return res; @@ -4285,7 +4294,7 @@ INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value, if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SSIZE_T res = REAL(lgetxattr)(path, name, value, size); if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res); return res; @@ -4297,7 +4306,7 @@ INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value, if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. SSIZE_T res = REAL(fgetxattr)(fd, name, value, size); if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res); return res; @@ -4316,7 +4325,7 @@ INTERCEPTOR(int, getresuid, void *ruid, void *euid, void *suid) { COMMON_INTERCEPTOR_ENTER(ctx, getresuid, ruid, euid, suid); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getresuid)(ruid, euid, suid); if (res >= 0) { if (ruid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ruid, uid_t_sz); @@ -4330,7 +4339,7 @@ INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) { COMMON_INTERCEPTOR_ENTER(ctx, getresgid, rgid, egid, sgid); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getresgid)(rgid, egid, sgid); if (res >= 0) { if (rgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rgid, gid_t_sz); @@ -4355,7 +4364,7 @@ INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) { COMMON_INTERCEPTOR_ENTER(ctx, getifaddrs, ifap); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(getifaddrs)(ifap); if (res == 0 && ifap) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifap, sizeof(void *)); @@ -4391,7 +4400,7 @@ INTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) { COMMON_INTERCEPTOR_ENTER(ctx, if_indextoname, ifindex, ifname); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. char *res = REAL(if_indextoname)(ifindex, ifname); if (res && ifname) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1); @@ -4419,7 +4428,7 @@ INTERCEPTOR(int, capget, void *hdrp, void *datap) { COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(capget)(hdrp, datap); if (res == 0 && datap) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, __user_cap_data_struct_sz); @@ -4520,7 +4529,7 @@ INTERCEPTOR(int, ftime, __sanitizer_timeb *tp) { COMMON_INTERCEPTOR_ENTER(ctx, ftime, tp); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(ftime)(tp); if (tp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, sizeof(*tp)); @@ -4538,7 +4547,7 @@ INTERCEPTOR(void, xdrmem_create, __sanitizer_XDR *xdrs, uptr addr, COMMON_INTERCEPTOR_ENTER(ctx, xdrmem_create, xdrs, addr, size, op); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. REAL(xdrmem_create)(xdrs, addr, size, op); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs)); if (op == __sanitizer_XDR_ENCODE) { @@ -4553,14 +4562,14 @@ INTERCEPTOR(void, xdrstdio_create, __sanitizer_XDR *xdrs, void *file, int op) { COMMON_INTERCEPTOR_ENTER(ctx, xdrstdio_create, xdrs, file, op); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. REAL(xdrstdio_create)(xdrs, file, op); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs)); } // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See -// https://code.google.com/p/address-sanitizer/issues/detail?id=321. +// https://github.com/google/sanitizers/issues/321. #define XDR_INTERCEPTOR(F, T) \ INTERCEPTOR(int, F, __sanitizer_XDR *xdrs, T *p) { \ void *ctx; \ @@ -4614,7 +4623,7 @@ INTERCEPTOR(int, xdr_bytes, __sanitizer_XDR *xdrs, char **p, unsigned *sizep, } // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(xdr_bytes)(xdrs, p, sizep, maxsize); if (p && sizep && xdrs->x_op == __sanitizer_XDR_DECODE) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); @@ -4634,7 +4643,7 @@ INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p, } // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. int res = REAL(xdr_string)(xdrs, p, maxsize); if (p && xdrs->x_op == __sanitizer_XDR_DECODE) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); @@ -4686,7 +4695,7 @@ INTERCEPTOR(void *, tsearch, void *key, void **rootp, COMMON_INTERCEPTOR_ENTER(ctx, tsearch, key, rootp, compar); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. void *res = REAL(tsearch)(key, rootp, compar); if (res && *(void **)res == key) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(void *)); @@ -4768,7 +4777,7 @@ INTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) { INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, fopen, path, mode); - COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); + if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1); __sanitizer_FILE *res = REAL(fopen)(path, mode); COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path); @@ -4839,7 +4848,7 @@ INTERCEPTOR(__sanitizer_FILE *, open_memstream, char **ptr, SIZE_T *sizeloc) { COMMON_INTERCEPTOR_ENTER(ctx, open_memstream, ptr, sizeloc); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. __sanitizer_FILE *res = REAL(open_memstream)(ptr, sizeloc); if (res) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr)); @@ -4870,7 +4879,7 @@ INTERCEPTOR(__sanitizer_FILE *, fmemopen, void *buf, SIZE_T size, COMMON_INTERCEPTOR_ENTER(ctx, fmemopen, buf, size, mode); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=321. + // https://github.com/google/sanitizers/issues/321. __sanitizer_FILE *res = REAL(fmemopen)(buf, size, mode); if (res) unpoison_file(res); return res; @@ -5284,6 +5293,36 @@ INTERCEPTOR(SSIZE_T, process_vm_writev, int pid, __sanitizer_iovec *local_iov, #define INIT_PROCESS_VM_READV #endif +#if SANITIZER_INTERCEPT_CTERMID +INTERCEPTOR(char *, ctermid, char *s) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s); + char *res = REAL(ctermid)(s); + if (res) { + COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); + } + return res; +} +#define INIT_CTERMID COMMON_INTERCEPT_FUNCTION(ctermid); +#else +#define INIT_CTERMID +#endif + +#if SANITIZER_INTERCEPT_CTERMID_R +INTERCEPTOR(char *, ctermid_r, char *s) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s); + char *res = REAL(ctermid_r)(s); + if (res) { + COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); + } + return res; +} +#define INIT_CTERMID_R COMMON_INTERCEPT_FUNCTION(ctermid_r); +#else +#define INIT_CTERMID_R +#endif + static void InitializeCommonInterceptors() { static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1]; interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap(); @@ -5458,4 +5497,6 @@ static void InitializeCommonInterceptors() { INIT_PTHREAD_SETCANCEL; INIT_MINCORE; INIT_PROCESS_VM_READV; + INIT_CTERMID; + INIT_CTERMID_R; } diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cc index 1b65bced75..596f5bcd31 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "sanitizer_common.h" + #include "sanitizer_flags.h" #include "sanitizer_stackdepot.h" #include "sanitizer_stacktrace.h" @@ -46,6 +47,7 @@ void SetSandboxingCallback(void (*f)()) { } void ReportErrorSummary(const char *error_type, StackTrace *stack) { +#if !SANITIZER_GO if (!common_flags()->print_summary) return; if (stack->size == 0) { @@ -58,6 +60,7 @@ void ReportErrorSummary(const char *error_type, StackTrace *stack) { SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc); ReportErrorSummary(error_type, frame->info); frame->ClearAll(); +#endif } static void (*SoftRssLimitExceededCallback)(bool exceeded); @@ -116,8 +119,27 @@ void BackgroundThread(void *arg) { } } +void WriteToSyslog(const char *msg) { + InternalScopedString msg_copy(kErrorMessageBufferSize); + msg_copy.append("%s", msg); + char *p = msg_copy.data(); + char *q; + + // Print one line at a time. + // syslog, at least on Android, has an implicit message length limit. + do { + q = internal_strchr(p, '\n'); + if (q) + *q = '\0'; + WriteOneLineToSyslog(p); + if (q) + p = q + 1; + } while (q); +} + void MaybeStartBackgroudThread() { -#if SANITIZER_LINUX // Need to implement/test on other platforms. +#if SANITIZER_LINUX && \ + !SANITIZER_GO // Need to implement/test on other platforms. // Start the background thread if one of the rss limits is given. if (!common_flags()->hard_rss_limit_mb && !common_flags()->soft_rss_limit_mb) return; diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cc index 65d1e37f62..9f4f97224e 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cc @@ -18,9 +18,10 @@ namespace __sanitizer { #if SANITIZER_LINUX -void WriteToSyslog(const char *buffer) {} +bool ShouldLogAfterPrintf() { return false; } +void LogMessageOnPrintf(const char *str) {} #endif - +void WriteToSyslog(const char *buffer) {} void Abort() { internal__exit(1); } } // namespace __sanitizer diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc index 9098cec91f..eaa1446afd 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc @@ -55,6 +55,11 @@ static atomic_uint32_t dump_once_guard; // Ensure that CovDump runs only once. static atomic_uintptr_t coverage_counter; static atomic_uintptr_t caller_callee_counter; +static void ResetGlobalCounters() { + return atomic_store(&coverage_counter, 0, memory_order_relaxed); + return atomic_store(&caller_callee_counter, 0, memory_order_relaxed); +} + // pc_array is the array containing the covered PCs. // To make the pc_array thread- and async-signal-safe it has to be large enough. // 128M counters "ought to be enough for anybody" (4M on 32-bit). @@ -91,7 +96,7 @@ class CoverageData { void DumpAll(); ALWAYS_INLINE - void TraceBasicBlock(s32 *id); + void TraceBasicBlock(u32 *id); void InitializeGuardArray(s32 *guards); void InitializeGuards(s32 *guards, uptr n, const char *module_name, @@ -103,6 +108,7 @@ class CoverageData { uptr *data(); uptr size(); + uptr *buffer() const { return pc_buffer; } private: void DirectOpen(); @@ -128,6 +134,8 @@ class CoverageData { // Descriptor of the file mapped pc array. fd_t pc_fd; + uptr *pc_buffer; + // Vector of coverage guard arrays, protected by mu. InternalMmapVectorNoCtor guard_array_vec; @@ -204,6 +212,11 @@ void CoverageData::Enable() { atomic_store(&pc_array_size, kPcArrayMaxSize, memory_order_relaxed); } + pc_buffer = nullptr; + if (common_flags()->coverage_pc_buffer) + pc_buffer = reinterpret_cast(MmapNoReserveOrDie( + sizeof(uptr) * kPcArrayMaxSize, "CovInit::pc_buffer")); + cc_array = reinterpret_cast(MmapNoReserveOrDie( sizeof(uptr *) * kCcArrayMaxSize, "CovInit::cc_array")); atomic_store(&cc_array_size, kCcArrayMaxSize, memory_order_relaxed); @@ -226,7 +239,8 @@ void CoverageData::InitializeGuardArray(s32 *guards) { Enable(); // Make sure coverage is enabled at this point. s32 n = guards[0]; for (s32 j = 1; j <= n; j++) { - uptr idx = atomic_fetch_add(&pc_array_index, 1, memory_order_relaxed); + uptr idx = atomic_load_relaxed(&pc_array_index); + atomic_store_relaxed(&pc_array_index, idx + 1); guards[j] = -static_cast(idx + 1); } } @@ -240,6 +254,10 @@ void CoverageData::Disable() { UnmapOrDie(cc_array, sizeof(uptr *) * kCcArrayMaxSize); cc_array = nullptr; } + if (pc_buffer) { + UnmapOrDie(pc_buffer, sizeof(uptr) * kPcArrayMaxSize); + pc_buffer = nullptr; + } if (tr_event_array) { UnmapOrDie(tr_event_array, sizeof(tr_event_array[0]) * kTrEventArrayMaxSize + @@ -408,6 +426,7 @@ void CoverageData::Add(uptr pc, u32 *guard) { atomic_load(&pc_array_size, memory_order_acquire)); uptr counter = atomic_fetch_add(&coverage_counter, 1, memory_order_relaxed); pc_array[idx] = BundlePcAndCounter(pc, counter); + if (pc_buffer) pc_buffer[counter] = pc; } // Registers a pair caller=>callee. @@ -676,11 +695,11 @@ void CoverageData::DumpCallerCalleePairs() { // it once and then cache in the provided 'cache' storage. // // This function will eventually be inlined by the compiler. -void CoverageData::TraceBasicBlock(s32 *id) { +void CoverageData::TraceBasicBlock(u32 *id) { // Will trap here if // 1. coverage is not enabled at run-time. // 2. The array tr_event_array is full. - *tr_event_pointer = static_cast(*id - 1); + *tr_event_pointer = *id - 1; tr_event_pointer++; } @@ -914,15 +933,18 @@ uptr __sanitizer_get_total_unique_caller_callee_pairs() { } SANITIZER_INTERFACE_ATTRIBUTE -void __sanitizer_cov_trace_func_enter(s32 *id) { +void __sanitizer_cov_trace_func_enter(u32 *id) { + __sanitizer_cov_with_check(id); coverage_data.TraceBasicBlock(id); } SANITIZER_INTERFACE_ATTRIBUTE -void __sanitizer_cov_trace_basic_block(s32 *id) { +void __sanitizer_cov_trace_basic_block(u32 *id) { + __sanitizer_cov_with_check(id); coverage_data.TraceBasicBlock(id); } SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_reset_coverage() { + ResetGlobalCounters(); coverage_data.ReinitializeGuards(); internal_bzero_aligned16( coverage_data.data(), @@ -934,6 +956,12 @@ uptr __sanitizer_get_coverage_guards(uptr **data) { return coverage_data.size(); } +SANITIZER_INTERFACE_ATTRIBUTE +uptr __sanitizer_get_coverage_pc_buffer(uptr **data) { + *data = coverage_data.buffer(); + return __sanitizer_get_total_unique_coverage(); +} + SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_number_of_counters() { return coverage_data.GetNumberOf8bitCounters(); diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/src/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc index e742d85466..c28f7f4a60 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc @@ -56,7 +56,7 @@ COMMON_FLAG( "Mention name of executable when reporting error and " "append executable name to logs (as in \"log_path.exe_name.pid\").") COMMON_FLAG( - bool, log_to_syslog, SANITIZER_ANDROID, + bool, log_to_syslog, SANITIZER_ANDROID || SANITIZER_MAC, "Write all sanitizer output to syslog in addition to other means of " "logging.") COMMON_FLAG( @@ -79,6 +79,8 @@ COMMON_FLAG(bool, handle_segv, SANITIZER_NEEDS_SEGV, "If set, registers the tool's custom SIGSEGV/SIGBUS handler.") COMMON_FLAG(bool, handle_abort, false, "If set, registers the tool's custom SIGABRT handler.") +COMMON_FLAG(bool, handle_sigill, false, + "If set, registers the tool's custom SIGILL handler.") COMMON_FLAG(bool, handle_sigfpe, true, "If set, registers the tool's custom SIGFPE handler.") COMMON_FLAG(bool, allow_user_segv_handler, false, @@ -142,6 +144,9 @@ COMMON_FLAG(bool, coverage_direct, SANITIZER_ANDROID, COMMON_FLAG(const char *, coverage_dir, ".", "Target directory for coverage dumps. Defaults to the current " "directory.") +COMMON_FLAG(bool, coverage_pc_buffer, true, + "If set (and if 'coverage' is set too), the pcs would be collected " + "in a buffer.") COMMON_FLAG(bool, full_address_space, false, "Sanitize complete address space; " "by default kernel area on 32-bit platforms will not be sanitized") @@ -192,3 +197,6 @@ COMMON_FLAG( bool, abort_on_error, SANITIZER_MAC, "If set, the tool calls abort() instead of _exit() after printing the " "error report.") +COMMON_FLAG(bool, suppress_equal_pcs, true, + "Deduplicate multiple reports for single source location in " + "halt_on_error=false mode (asan only).") diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h b/src/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h index dfc9d2833b..e83eed0830 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h @@ -117,7 +117,10 @@ using namespace __sanitizer; // NOLINT // Common defs. #define INLINE inline #define INTERFACE_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE -#define WEAK SANITIZER_WEAK_ATTRIBUTE +#define SANITIZER_WEAK_DEFAULT_IMPL \ + extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE +#define SANITIZER_WEAK_CXX_DEFAULT_IMPL \ + extern "C++" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE // Platform-specific defs. #if defined(_MSC_VER) diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_libc.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_libc.cc index 43e4546946..cf31e68965 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_libc.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_libc.cc @@ -175,6 +175,19 @@ uptr internal_strlen(const char *s) { return i; } +uptr internal_strlcat(char *dst, const char *src, uptr maxlen) { + const uptr srclen = internal_strlen(src); + const uptr dstlen = internal_strnlen(dst, maxlen); + if (dstlen == maxlen) return maxlen + srclen; + if (srclen < maxlen - dstlen) { + internal_memmove(dst + dstlen, src, srclen + 1); + } else { + internal_memmove(dst + dstlen, src, maxlen - dstlen - 1); + dst[maxlen - 1] = '\0'; + } + return dstlen + srclen; +} + char *internal_strncat(char *dst, const char *src, uptr n) { uptr len = internal_strlen(dst); uptr i; @@ -184,6 +197,17 @@ char *internal_strncat(char *dst, const char *src, uptr n) { return dst; } +uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) { + const uptr srclen = internal_strlen(src); + if (srclen < maxlen) { + internal_memmove(dst, src, srclen + 1); + } else if (maxlen != 0) { + internal_memmove(dst, src, maxlen - 1); + dst[maxlen - 1] = '\0'; + } + return srclen; +} + char *internal_strncpy(char *dst, const char *src, uptr n) { uptr i; for (i = 0; i < n && src[i]; i++) diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_libc.h b/src/compiler-rt/lib/sanitizer_common/sanitizer_libc.h index 99de140ec1..df28677c67 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_libc.h +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_libc.h @@ -43,8 +43,10 @@ uptr internal_strcspn(const char *s, const char *reject); char *internal_strdup(const char *s); char *internal_strndup(const char *s, uptr n); uptr internal_strlen(const char *s); +uptr internal_strlcat(char *dst, const char *src, uptr maxlen); char *internal_strncat(char *dst, const char *src, uptr n); int internal_strncmp(const char *s1, const char *s2, uptr n); +uptr internal_strlcpy(char *dst, const char *src, uptr maxlen); char *internal_strncpy(char *dst, const char *src, uptr n); uptr internal_strnlen(const char *s, uptr maxlen); char *internal_strrchr(const char *s, int c); diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index a001c1a7de..cba38c8c30 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -89,7 +89,8 @@ const int FUTEX_WAKE = 1; // Are we using 32-bit or 64-bit Linux syscalls? // x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32 // but it still needs to use 64-bit syscalls. -#if SANITIZER_LINUX && (defined(__x86_64__) || SANITIZER_WORDSIZE == 64) +#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__powerpc64__) || \ + SANITIZER_WORDSIZE == 64) # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1 #else # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0 @@ -983,18 +984,91 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, : "x30", "memory"); return res; } -#endif // defined(__x86_64__) && SANITIZER_LINUX +#elif defined(__powerpc64__) +uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, + int *parent_tidptr, void *newtls, int *child_tidptr) { + long long res; +/* Stack frame offsets. */ +#if _CALL_ELF != 2 +#define FRAME_MIN_SIZE 112 +#define FRAME_TOC_SAVE 40 +#else +#define FRAME_MIN_SIZE 32 +#define FRAME_TOC_SAVE 24 +#endif + if (!fn || !child_stack) + return -EINVAL; + CHECK_EQ(0, (uptr)child_stack % 16); + child_stack = (char *)child_stack - 2 * sizeof(unsigned long long); + ((unsigned long long *)child_stack)[0] = (uptr)fn; + ((unsigned long long *)child_stack)[1] = (uptr)arg; -#if SANITIZER_ANDROID -#define PROP_VALUE_MAX 92 -extern "C" SANITIZER_WEAK_ATTRIBUTE int __system_property_get(const char *name, - char *value); -void GetExtraActivationFlags(char *buf, uptr size) { - CHECK(size > PROP_VALUE_MAX); - CHECK(&__system_property_get); - __system_property_get("asan.options", buf); + register int (*__fn)(void *) __asm__("r3") = fn; + register void *__cstack __asm__("r4") = child_stack; + register int __flags __asm__("r5") = flags; + register void * __arg __asm__("r6") = arg; + register int * __ptidptr __asm__("r7") = parent_tidptr; + register void * __newtls __asm__("r8") = newtls; + register int * __ctidptr __asm__("r9") = child_tidptr; + + __asm__ __volatile__( + /* fn, arg, child_stack are saved acrVoss the syscall */ + "mr 28, %5\n\t" + "mr 29, %6\n\t" + "mr 27, %8\n\t" + + /* syscall + r3 == flags + r4 == child_stack + r5 == parent_tidptr + r6 == newtls + r7 == child_tidptr */ + "mr 3, %7\n\t" + "mr 5, %9\n\t" + "mr 6, %10\n\t" + "mr 7, %11\n\t" + "li 0, %3\n\t" + "sc\n\t" + + /* Test if syscall was successful */ + "cmpdi cr1, 3, 0\n\t" + "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t" + "bne- cr1, 1f\n\t" + + /* Do the function call */ + "std 2, %13(1)\n\t" +#if _CALL_ELF != 2 + "ld 0, 0(28)\n\t" + "ld 2, 8(28)\n\t" + "mtctr 0\n\t" +#else + "mr 12, 28\n\t" + "mtctr 12\n\t" +#endif + "mr 3, 27\n\t" + "bctrl\n\t" + "ld 2, %13(1)\n\t" + + /* Call _exit(r3) */ + "li 0, %4\n\t" + "sc\n\t" + + /* Return to parent */ + "1:\n\t" + "mr %0, 3\n\t" + : "=r" (res) + : "0" (-1), "i" (EINVAL), + "i" (__NR_clone), "i" (__NR_exit), + "r" (__fn), "r" (__cstack), "r" (__flags), + "r" (__arg), "r" (__ptidptr), "r" (__newtls), + "r" (__ctidptr), "i" (FRAME_MIN_SIZE), "i" (FRAME_TOC_SAVE) + : "cr0", "cr1", "memory", "ctr", + "r0", "r29", "r27", "r28"); + return res; } +#endif // defined(__x86_64__) && SANITIZER_LINUX +#if SANITIZER_ANDROID #if __ANDROID_API__ < 21 extern "C" __attribute__((weak)) int dl_iterate_phdr( int (*)(struct dl_phdr_info *, size_t, void *), void *); @@ -1040,6 +1114,8 @@ AndroidApiLevel AndroidGetApiLevel() { bool IsDeadlySignal(int signum) { if (common_flags()->handle_abort && signum == SIGABRT) return true; + if (common_flags()->handle_sigill && signum == SIGILL) + return true; if (common_flags()->handle_sigfpe && signum == SIGFPE) return true; return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv; @@ -1143,6 +1219,14 @@ void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { #endif } +void DisableReexec() { + // No need to re-exec on Linux. +} + +void MaybeReexec() { + // No need to re-exec on Linux. +} + } // namespace __sanitizer #endif // SANITIZER_FREEBSD || SANITIZER_LINUX diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/src/compiler-rt/lib/sanitizer_common/sanitizer_linux.h index d996f8c322..77bfbd1568 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_linux.h +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_linux.h @@ -44,7 +44,8 @@ uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5); // internal_sigaction instead. int internal_sigaction_norestorer(int signum, const void *act, void *oldact); void internal_sigdelset(__sanitizer_sigset_t *set, int signum); -#if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) \ + || defined(__powerpc64__) uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, int *parent_tidptr, void *newtls, int *child_tidptr); #endif diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc index 4b583bfa41..04031d2552 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -166,11 +166,15 @@ static uptr g_tls_size; # define DL_INTERNAL_FUNCTION #endif -#if defined(__mips__) +#if defined(__mips__) || defined(__powerpc64__) // TlsPreTcbSize includes size of struct pthread_descr and size of tcb // head structure. It lies before the static tls blocks. static uptr TlsPreTcbSize() { - const uptr kTcbHead = 16; +# if defined(__mips__) + const uptr kTcbHead = 16; // sizeof (tcbhead_t) +# elif defined(__powerpc64__) + const uptr kTcbHead = 88; // sizeof (tcbhead_t) +# endif const uptr kTlsAlign = 16; const uptr kTlsPreTcbSize = (ThreadDescriptorSize() + kTcbHead + kTlsAlign - 1) & ~(kTlsAlign - 1); @@ -201,9 +205,9 @@ void InitTlsSize() { } #if (defined(__x86_64__) || defined(__i386__) || defined(__mips__) \ - || defined(__aarch64__)) \ + || defined(__aarch64__) || defined(__powerpc64__)) \ && SANITIZER_LINUX && !SANITIZER_ANDROID -// sizeof(struct thread) from glibc. +// sizeof(struct pthread) from glibc. static atomic_uintptr_t kThreadDescriptorSize; uptr ThreadDescriptorSize() { @@ -218,7 +222,12 @@ uptr ThreadDescriptorSize() { char *end; int minor = internal_simple_strtoll(buf + 8, &end, 10); if (end != buf + 8 && (*end == '\0' || *end == '.')) { - /* sizeof(struct thread) values from various glibc versions. */ + int patch = 0; + if (*end == '.') + // strtoll will return 0 if no valid conversion could be performed + patch = internal_simple_strtoll(end + 1, nullptr, 10); + + /* sizeof(struct pthread) values from various glibc versions. */ if (SANITIZER_X32) val = 1728; // Assume only one particular version for x32. else if (minor <= 3) @@ -231,9 +240,9 @@ uptr ThreadDescriptorSize() { val = FIRST_32_SECOND_64(1136, 1712); else if (minor == 10) val = FIRST_32_SECOND_64(1168, 1776); - else if (minor <= 12) + else if (minor == 11 || (minor == 12 && patch == 1)) val = FIRST_32_SECOND_64(1168, 2288); - else if (minor == 13) + else if (minor <= 13) val = FIRST_32_SECOND_64(1168, 2304); else val = FIRST_32_SECOND_64(1216, 2304); @@ -254,6 +263,10 @@ uptr ThreadDescriptorSize() { val = 1776; atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed); return val; +#elif defined(__powerpc64__) + val = 1776; // from glibc.ppc64le 2.20-8.fc21 + atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed); + return val; #endif return 0; } @@ -285,6 +298,15 @@ uptr ThreadSelf() { descr_addr = thread_pointer - kTlsTcbOffset - TlsPreTcbSize(); # elif defined(__aarch64__) descr_addr = reinterpret_cast(__builtin_thread_pointer()); +# elif defined(__powerpc64__) + // PPC64LE uses TLS variant I. The thread pointer (in GPR 13) + // points to the end of the TCB + 0x7000. The pthread_descr structure is + // immediately in front of the TCB. TlsPreTcbSize() includes the size of the + // TCB and the size of pthread_descr. + const uptr kTlsTcbOffset = 0x7000; + uptr thread_pointer; + asm("addi %0,13,%1" : "=r"(thread_pointer) : "I"(-kTlsTcbOffset)); + descr_addr = thread_pointer - TlsPreTcbSize(); # else # error "unsupported CPU arch" # endif @@ -320,7 +342,7 @@ static void GetTls(uptr *addr, uptr *size) { *size = GetTlsSize(); *addr -= *size; *addr += ThreadDescriptorSize(); -# elif defined(__mips__) || defined(__aarch64__) +# elif defined(__mips__) || defined(__aarch64__) || defined(__powerpc64__) *addr = ThreadSelf(); *size = GetTlsSize(); # else @@ -507,16 +529,16 @@ void AndroidLogInit() { atomic_store(&android_log_initialized, 1, memory_order_release); } -static bool IsSyslogAvailable() { +static bool ShouldLogAfterPrintf() { return atomic_load(&android_log_initialized, memory_order_acquire); } #else void AndroidLogInit() {} -static bool IsSyslogAvailable() { return true; } +static bool ShouldLogAfterPrintf() { return true; } #endif // SANITIZER_ANDROID -static void WriteOneLineToSyslog(const char *s) { +void WriteOneLineToSyslog(const char *s) { #if SANITIZER_ANDROID &&__ANDROID_API__ < 21 __android_log_write(ANDROID_LOG_INFO, NULL, s); #else @@ -524,24 +546,11 @@ static void WriteOneLineToSyslog(const char *s) { #endif } -void WriteToSyslog(const char *buffer) { - if (!IsSyslogAvailable()) - return; - char *copy = internal_strdup(buffer); - char *p = copy; - char *q; - // syslog, at least on Android, has an implicit message length limit. - // Print one line at a time. - do { - q = internal_strchr(p, '\n'); - if (q) - *q = '\0'; - WriteOneLineToSyslog(p); - if (q) - p = q + 1; - } while (q); - InternalFree(copy); +void LogMessageOnPrintf(const char *str) { + if (common_flags()->log_to_syslog && ShouldLogAfterPrintf()) + WriteToSyslog(str); } + #endif // SANITIZER_LINUX } // namespace __sanitizer diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc index 3151cf8b91..715509d307 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc @@ -13,6 +13,7 @@ #include "sanitizer_platform.h" #if SANITIZER_MAC +#include "sanitizer_mac.h" // Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so // the clients will most certainly use 64-bit ones as well. @@ -25,7 +26,6 @@ #include "sanitizer_flags.h" #include "sanitizer_internal_defs.h" #include "sanitizer_libc.h" -#include "sanitizer_mac.h" #include "sanitizer_placement_new.h" #include "sanitizer_platform_limits_posix.h" #include "sanitizer_procmaps.h" @@ -36,6 +36,23 @@ extern char **environ; #endif +#if defined(__has_include) && __has_include() +#define SANITIZER_OS_TRACE 1 +#include +#else +#define SANITIZER_OS_TRACE 0 +#endif + +#if !SANITIZER_IOS +#include // for _NSGetArgv and _NSGetEnviron +#else +extern "C" { + extern char ***_NSGetArgv(void); +} +#endif + +#include +#include // for dladdr() #include #include #include @@ -52,6 +69,7 @@ extern char **environ; #include #include #include +#include namespace __sanitizer { @@ -147,9 +165,30 @@ uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, return sigprocmask(how, set, oldset); } +// Doesn't call pthread_atfork() handlers. +extern "C" pid_t __fork(void); + int internal_fork() { - // TODO(glider): this may call user's pthread_atfork() handlers which is bad. - return fork(); + return __fork(); +} + +int internal_forkpty(int *amaster) { + int master, slave; + if (openpty(&master, &slave, nullptr, nullptr, nullptr) == -1) return -1; + int pid = __fork(); + if (pid == -1) { + close(master); + close(slave); + return -1; + } + if (pid == 0) { + close(master); + CHECK_EQ(login_tty(slave), 0); + } else { + *amaster = master; + close(slave); + } + return pid; } uptr internal_rename(const char *oldpath, const char *newpath) { @@ -180,7 +219,7 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, uptr stacksize = pthread_get_stacksize_np(pthread_self()); // pthread_get_stacksize_np() returns an incorrect stack size for the main // thread on Mavericks. See - // https://code.google.com/p/address-sanitizer/issues/detail?id=261 + // https://github.com/google/sanitizers/issues/261 if ((GetMacosVersion() >= MACOS_VERSION_MAVERICKS) && at_initialization && stacksize == (1 << 19)) { struct rlimit rl; @@ -371,8 +410,67 @@ uptr GetRSS() { return info.resident_size; } -void *internal_start_thread(void (*func)(void *arg), void *arg) { return 0; } -void internal_join_thread(void *th) { } +void *internal_start_thread(void(*func)(void *arg), void *arg) { + // Start the thread with signals blocked, otherwise it can steal user signals. + __sanitizer_sigset_t set, old; + internal_sigfillset(&set); + internal_sigprocmask(SIG_SETMASK, &set, &old); + pthread_t th; + pthread_create(&th, 0, (void*(*)(void *arg))func, arg); + internal_sigprocmask(SIG_SETMASK, &old, 0); + return th; +} + +void internal_join_thread(void *th) { pthread_join((pthread_t)th, 0); } + +static BlockingMutex syslog_lock(LINKER_INITIALIZED); + +void WriteOneLineToSyslog(const char *s) { + syslog_lock.CheckLocked(); + asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s); +} + +void LogMessageOnPrintf(const char *str) { + // Log all printf output to CrashLog. + if (common_flags()->abort_on_error) + CRAppendCrashLogMessage(str); +} + +void LogFullErrorReport(const char *buffer) { + // Log with os_trace. This will make it into the crash log. +#if SANITIZER_OS_TRACE + if (GetMacosVersion() >= MACOS_VERSION_YOSEMITE) { + // os_trace requires the message (format parameter) to be a string literal. + if (internal_strncmp(SanitizerToolName, "AddressSanitizer", + sizeof("AddressSanitizer") - 1) == 0) + os_trace("Address Sanitizer reported a failure."); + else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer", + sizeof("UndefinedBehaviorSanitizer") - 1) == 0) + os_trace("Undefined Behavior Sanitizer reported a failure."); + else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer", + sizeof("ThreadSanitizer") - 1) == 0) + os_trace("Thread Sanitizer reported a failure."); + else + os_trace("Sanitizer tool reported a failure."); + + if (common_flags()->log_to_syslog) + os_trace("Consult syslog for more information."); + } +#endif + + // Log to syslog. + // The logging on OS X may call pthread_create so we need the threading + // environment to be fully initialized. Also, this should never be called when + // holding the thread registry lock since that may result in a deadlock. If + // the reporting thread holds the thread registry mutex, and asl_log waits + // for GCD to dispatch a new thread, the process will deadlock, because the + // pthread_create wrapper needs to acquire the lock as well. + BlockingMutexLock l(&syslog_lock); + if (common_flags()->log_to_syslog) + WriteToSyslog(buffer); + + // The report is added to CrashLog as part of logging all of Printf output. +} void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { ucontext_t *ucontext = (ucontext_t*)context; @@ -401,6 +499,173 @@ void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { # endif } +static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; +LowLevelAllocator allocator_for_env; + +// Change the value of the env var |name|, leaking the original value. +// If |name_value| is NULL, the variable is deleted from the environment, +// otherwise the corresponding "NAME=value" string is replaced with +// |name_value|. +void LeakyResetEnv(const char *name, const char *name_value) { + char **env = GetEnviron(); + uptr name_len = internal_strlen(name); + while (*env != 0) { + uptr len = internal_strlen(*env); + if (len > name_len) { + const char *p = *env; + if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') { + // Match. + if (name_value) { + // Replace the old value with the new one. + *env = const_cast(name_value); + } else { + // Shift the subsequent pointers back. + char **del = env; + do { + del[0] = del[1]; + } while (*del++); + } + } + } + env++; + } +} + +static bool reexec_disabled = false; + +void DisableReexec() { + reexec_disabled = true; +} + +extern "C" double dyldVersionNumber; +static const double kMinDyldVersionWithAutoInterposition = 360.0; + +bool DyldNeedsEnvVariable() { + // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if + // DYLD_INSERT_LIBRARIES is not set. However, checking OS version via + // GetMacosVersion() doesn't work for the simulator. Let's instead check + // `dyldVersionNumber`, which is exported by dyld, against a known version + // number from the first OS release where this appeared. + return dyldVersionNumber < kMinDyldVersionWithAutoInterposition; +} + +void MaybeReexec() { + if (reexec_disabled) return; + + // Make sure the dynamic runtime library is preloaded so that the + // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec + // ourselves. + Dl_info info; + CHECK(dladdr((void*)((uptr)&__sanitizer_report_error_summary), &info)); + char *dyld_insert_libraries = + const_cast(GetEnv(kDyldInsertLibraries)); + uptr old_env_len = dyld_insert_libraries ? + internal_strlen(dyld_insert_libraries) : 0; + uptr fname_len = internal_strlen(info.dli_fname); + const char *dylib_name = StripModuleName(info.dli_fname); + uptr dylib_name_len = internal_strlen(dylib_name); + + bool lib_is_in_env = dyld_insert_libraries && + internal_strstr(dyld_insert_libraries, dylib_name); + if (DyldNeedsEnvVariable() && !lib_is_in_env) { + // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime + // library. + InternalScopedString program_name(1024); + uint32_t buf_size = program_name.size(); + _NSGetExecutablePath(program_name.data(), &buf_size); + char *new_env = const_cast(info.dli_fname); + if (dyld_insert_libraries) { + // Append the runtime dylib name to the existing value of + // DYLD_INSERT_LIBRARIES. + new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2); + internal_strncpy(new_env, dyld_insert_libraries, old_env_len); + new_env[old_env_len] = ':'; + // Copy fname_len and add a trailing zero. + internal_strncpy(new_env + old_env_len + 1, info.dli_fname, + fname_len + 1); + // Ok to use setenv() since the wrappers don't depend on the value of + // asan_inited. + setenv(kDyldInsertLibraries, new_env, /*overwrite*/1); + } else { + // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name. + setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); + } + VReport(1, "exec()-ing the program with\n"); + VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env); + VReport(1, "to enable wrappers.\n"); + execv(program_name.data(), *_NSGetArgv()); + + // We get here only if execv() failed. + Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, " + "which is required for the sanitizer to work. We tried to set the " + "environment variable and re-execute itself, but execv() failed, " + "possibly because of sandbox restrictions. Make sure to launch the " + "executable with:\n%s=%s\n", kDyldInsertLibraries, new_env); + CHECK("execv failed" && 0); + } + + if (!lib_is_in_env) + return; + + // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove + // the dylib from the environment variable, because interceptors are installed + // and we don't want our children to inherit the variable. + + uptr env_name_len = internal_strlen(kDyldInsertLibraries); + // Allocate memory to hold the previous env var name, its value, the '=' + // sign and the '\0' char. + char *new_env = (char*)allocator_for_env.Allocate( + old_env_len + 2 + env_name_len); + CHECK(new_env); + internal_memset(new_env, '\0', old_env_len + 2 + env_name_len); + internal_strncpy(new_env, kDyldInsertLibraries, env_name_len); + new_env[env_name_len] = '='; + char *new_env_pos = new_env + env_name_len + 1; + + // Iterate over colon-separated pieces of |dyld_insert_libraries|. + char *piece_start = dyld_insert_libraries; + char *piece_end = NULL; + char *old_env_end = dyld_insert_libraries + old_env_len; + do { + if (piece_start[0] == ':') piece_start++; + piece_end = internal_strchr(piece_start, ':'); + if (!piece_end) piece_end = dyld_insert_libraries + old_env_len; + if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break; + uptr piece_len = piece_end - piece_start; + + char *filename_start = + (char *)internal_memrchr(piece_start, '/', piece_len); + uptr filename_len = piece_len; + if (filename_start) { + filename_start += 1; + filename_len = piece_len - (filename_start - piece_start); + } else { + filename_start = piece_start; + } + + // If the current piece isn't the runtime library name, + // append it to new_env. + if ((dylib_name_len != filename_len) || + (internal_memcmp(filename_start, dylib_name, dylib_name_len) != 0)) { + if (new_env_pos != new_env + env_name_len + 1) { + new_env_pos[0] = ':'; + new_env_pos++; + } + internal_strncpy(new_env_pos, piece_start, piece_len); + new_env_pos += piece_len; + } + // Move on to the next piece. + piece_start = piece_end; + } while (piece_start < old_env_end); + + // Can't use setenv() here, because it requires the allocator to be + // initialized. + // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in + // a separate function called after InitializeAllocator(). + if (new_env_pos == new_env + env_name_len + 1) new_env = NULL; + LeakyResetEnv(kDyldInsertLibraries, new_env); +} + } // namespace __sanitizer #endif // SANITIZER_MAC diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_mac.h b/src/compiler-rt/lib/sanitizer_common/sanitizer_mac.h index 50dbe93226..6e2b84f432 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_mac.h +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_mac.h @@ -13,6 +13,7 @@ #ifndef SANITIZER_MAC_H #define SANITIZER_MAC_H +#include "sanitizer_common.h" #include "sanitizer_platform.h" #if SANITIZER_MAC #include "sanitizer_posix.h" @@ -37,5 +38,18 @@ char **GetEnviron(); } // namespace __sanitizer +extern "C" { +static char __crashreporter_info_buff__[kErrorMessageBufferSize] = {}; +static const char *__crashreporter_info__ __attribute__((__used__)) = + &__crashreporter_info_buff__[0]; +asm(".desc ___crashreporter_info__, 0x10"); +} // extern "C" +static BlockingMutex crashreporter_info_mutex(LINKER_INITIALIZED); + +INLINE void CRAppendCrashLogMessage(const char *msg) { + BlockingMutexLock l(&crashreporter_info_mutex); + internal_strlcat(__crashreporter_info_buff__, msg, + sizeof(__crashreporter_info_buff__)); } + #endif // SANITIZER_MAC #endif // SANITIZER_MAC_H diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc b/src/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc index 33e9d96b8c..149857c168 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc @@ -27,10 +27,8 @@ #include "sanitizer_common/sanitizer_mac.h" // Similar code is used in Google Perftools, -// http://code.google.com/p/google-perftools. +// https://github.com/gperftools/gperftools. -// TODO(glider): do we need both zones? -static malloc_zone_t *system_malloc_zone = 0; static malloc_zone_t sanitizer_zone; INTERCEPTOR(malloc_zone_t *, malloc_create_zone, @@ -58,7 +56,7 @@ INTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) { INTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) { // FIXME: ASan should support purgeable allocations. - // https://code.google.com/p/address-sanitizer/issues/detail?id=139 + // https://github.com/google/sanitizers/issues/139 COMMON_MALLOC_ENTER(); return &sanitizer_zone; } @@ -155,10 +153,7 @@ size_t __sanitizer_mz_size(malloc_zone_t* zone, const void* ptr) { extern "C" SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_mz_malloc(malloc_zone_t *zone, uptr size) { - if (UNLIKELY(!COMMON_MALLOC_SANITIZER_INITIALIZED)) { - CHECK(system_malloc_zone); - return malloc_zone_malloc(system_malloc_zone, size); - } + COMMON_MALLOC_ENTER(); COMMON_MALLOC_MALLOC(size); return p; } @@ -184,36 +179,23 @@ void *__sanitizer_mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) { extern "C" SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_mz_valloc(malloc_zone_t *zone, size_t size) { - if (UNLIKELY(!COMMON_MALLOC_SANITIZER_INITIALIZED)) { - CHECK(system_malloc_zone); - return malloc_zone_valloc(system_malloc_zone, size); - } + COMMON_MALLOC_ENTER(); COMMON_MALLOC_VALLOC(size); return p; } -#define GET_ZONE_FOR_PTR(ptr) \ - malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); \ - const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name - -void ALWAYS_INLINE free_common(void *context, void *ptr) { - if (!ptr) return; - // FIXME: need to retire this flag. - if (!COMMON_MALLOC_IGNORE_INVALID_FREE) { - COMMON_MALLOC_FREE(ptr); - } else { - GET_ZONE_FOR_PTR(ptr); - COMMON_MALLOC_REPORT_FREE_UNALLOCATED(ptr, zone_ptr, zone_name); - } -} - // TODO(glider): the allocation callbacks need to be refactored. extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_mz_free(malloc_zone_t *zone, void *ptr) { - free_common(zone, ptr); + if (!ptr) return; + COMMON_MALLOC_FREE(ptr); } +#define GET_ZONE_FOR_PTR(ptr) \ + malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); \ + const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name + extern "C" SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_mz_realloc(malloc_zone_t *zone, void *ptr, size_t new_size) { @@ -246,10 +228,7 @@ void __sanitizer_mz_destroy(malloc_zone_t* zone) { extern "C" SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_mz_memalign(malloc_zone_t *zone, size_t align, size_t size) { - if (UNLIKELY(!COMMON_MALLOC_SANITIZER_INITIALIZED)) { - CHECK(system_malloc_zone); - return malloc_zone_memalign(system_malloc_zone, align, size); - } + COMMON_MALLOC_ENTER(); COMMON_MALLOC_MEMALIGN(align, size); return p; } diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/src/compiler-rt/lib/sanitizer_common/sanitizer_platform.h index a1da6150fb..841cceb510 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_platform.h +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_platform.h @@ -81,23 +81,13 @@ # define SANITIZER_X32 0 #endif -// VMA size definition for architecture that support multiple sizes. -// AArch64 has 3 VMA sizes: 39, 42 and 48. -#if !defined(SANITIZER_AARCH64_VMA) -# define SANITIZER_AARCH64_VMA 39 -#else -# if SANITIZER_AARCH64_VMA != 39 && SANITIZER_AARCH64_VMA != 42 -# error "invalid SANITIZER_AARCH64_VMA size" -# endif -#endif - // By default we allow to use SizeClassAllocator64 on 64-bit platform. // But in some cases (e.g. AArch64's 39-bit address space) SizeClassAllocator64 // does not work well and we need to fallback to SizeClassAllocator32. // For such platforms build this code with -DSANITIZER_CAN_USE_ALLOCATOR64=0 or // change the definition of SANITIZER_CAN_USE_ALLOCATOR64 here. #ifndef SANITIZER_CAN_USE_ALLOCATOR64 -# if defined(__mips64) || (defined(__aarch64__) && SANITIZER_AARCH64_VMA == 39) +# if defined(__mips64) || defined(__aarch64__) # define SANITIZER_CAN_USE_ALLOCATOR64 0 # else # define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64) @@ -105,16 +95,9 @@ #endif // The range of addresses which can be returned my mmap. -// FIXME: this value should be different on different platforms, -// e.g. on AArch64 it is most likely (1ULL << 39). Larger values will still work -// but will consume more memory for TwoLevelByteMap. -#if defined(__aarch64__) -# if SANITIZER_AARCH64_VMA == 39 -# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 39) -# elif SANITIZER_AARCH64_VMA == 42 -# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 42) -# endif -#elif defined(__mips__) +// FIXME: this value should be different on different platforms. Larger values +// will still work but will consume more memory for TwoLevelByteMap. +#if defined(__mips__) # define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 40) #else # define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47) @@ -144,10 +127,8 @@ #define SANITIZER_USES_UID16_SYSCALLS 0 #endif -#if defined(__mips__) || (defined(__aarch64__) && SANITIZER_AARCH64_VMA == 39) +#if defined(__mips__) # define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 10) -#elif defined(__aarch64__) && SANITIZER_AARCH64_VMA == 42 -# define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 11) #else # define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 12) #endif diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/src/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 89bfe98897..430ad48398 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -260,6 +260,8 @@ #define SANITIZER_INTERCEPT_PTHREAD_SETCANCEL SI_NOT_WINDOWS #define SANITIZER_INTERCEPT_MINCORE SI_LINUX #define SANITIZER_INTERCEPT_PROCESS_VM_READV SI_LINUX +#define SANITIZER_INTERCEPT_CTERMID SI_LINUX || SI_MAC || SI_FREEBSD +#define SANITIZER_INTERCEPT_CTERMID_R SI_MAC || SI_FREEBSD #define SANITIZER_INTERCEPTOR_HOOKS SI_LINUX diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc index 7aebc9c00b..b642cba0fe 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -123,6 +123,10 @@ # include # ifdef __arm__ typedef struct user_fpregs elf_fpregset_t; +# define ARM_VFPREGS_SIZE_ASAN (32 * 8 /*fpregs*/ + 4 /*fpscr*/) +# if !defined(ARM_VFPREGS_SIZE) +# define ARM_VFPREGS_SIZE ARM_VFPREGS_SIZE_ASAN +# endif # endif # endif # include @@ -333,21 +337,24 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); int ptrace_peektext = PTRACE_PEEKTEXT; int ptrace_peekdata = PTRACE_PEEKDATA; int ptrace_peekuser = PTRACE_PEEKUSER; -#if defined(PT_GETREGS) && defined(PT_SETREGS) +#if (defined(PTRACE_GETREGS) && defined(PTRACE_SETREGS)) || \ + (defined(PT_GETREGS) && defined(PT_SETREGS)) int ptrace_getregs = PTRACE_GETREGS; int ptrace_setregs = PTRACE_SETREGS; #else int ptrace_getregs = -1; int ptrace_setregs = -1; #endif -#if defined(PT_GETFPREGS) && defined(PT_SETFPREGS) +#if (defined(PTRACE_GETFPREGS) && defined(PTRACE_SETFPREGS)) || \ + (defined(PT_GETFPREGS) && defined(PT_SETFPREGS)) int ptrace_getfpregs = PTRACE_GETFPREGS; int ptrace_setfpregs = PTRACE_SETFPREGS; #else int ptrace_getfpregs = -1; int ptrace_setfpregs = -1; #endif -#if defined(PT_GETFPXREGS) && defined(PT_SETFPXREGS) +#if (defined(PTRACE_GETFPXREGS) && defined(PTRACE_SETFPXREGS)) || \ + (defined(PT_GETFPXREGS) && defined(PT_SETFPXREGS)) int ptrace_getfpxregs = PTRACE_GETFPXREGS; int ptrace_setfpxregs = PTRACE_SETFPXREGS; #else @@ -1261,4 +1268,8 @@ CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, close); CHECK_TYPE_SIZE(sem_t); #endif +#if SANITIZER_LINUX && defined(__arm__) +COMPILER_CHECK(ARM_VFPREGS_SIZE == ARM_VFPREGS_SIZE_ASAN); +#endif + #endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc index 9ad66bec2a..5ae68663df 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc @@ -112,14 +112,14 @@ uptr GetMaxVirtualAddress() { #endif // SANITIZER_WORDSIZE } -void *MmapOrDie(uptr size, const char *mem_type) { +void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { size = RoundUpTo(size, GetPageSizeCached()); uptr res = internal_mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); int reserrno; if (internal_iserror(res, &reserrno)) - ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); + ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno, raw_report); IncreaseTotalMmap(size); return (void *)res; } @@ -321,22 +321,6 @@ SignalContext SignalContext::Create(void *siginfo, void *context) { return SignalContext(context, addr, pc, sp, bp); } -// This function check is the built VMA matches the runtime one for -// architectures with multiple VMA size. -void CheckVMASize() { -#ifdef __aarch64__ - static const unsigned kBuiltVMA = SANITIZER_AARCH64_VMA; - unsigned maxRuntimeVMA = - (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); - if (kBuiltVMA != maxRuntimeVMA) { - Printf("WARNING: %s runtime VMA is not the one built for.\n", - SanitizerToolName); - Printf("\tBuilt VMA: %u bits\n", kBuiltVMA); - Printf("\tRuntime VMA: %u bits\n", maxRuntimeVMA); - } -#endif -} - } // namespace __sanitizer #endif // SANITIZER_POSIX diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_posix.h b/src/compiler-rt/lib/sanitizer_common/sanitizer_posix.h index 19fa505c52..c0426a0b23 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_posix.h +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_posix.h @@ -54,6 +54,7 @@ uptr internal_ptrace(int request, int pid, void *addr, void *data); uptr internal_waitpid(int pid, int *status, int options); int internal_fork(); +int internal_forkpty(int *amaster); // These functions call appropriate pthread_ functions directly, bypassing // the interceptor. They are weak and may not be present in some tools. diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc index d7b9f20414..c158eedae0 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -190,6 +190,7 @@ void InstallDeadlySignalHandlers(SignalHandlerType handler) { MaybeInstallSigaction(SIGBUS, handler); MaybeInstallSigaction(SIGABRT, handler); MaybeInstallSigaction(SIGFPE, handler); + MaybeInstallSigaction(SIGILL, handler); } #endif // SANITIZER_GO @@ -228,7 +229,7 @@ void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) { #endif } -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID || SANITIZER_GO int GetNamedMappingFd(const char *name, uptr size) { return -1; } diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_printf.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_printf.cc index 5f4725ec1d..434ebb93df 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_printf.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_printf.cc @@ -278,9 +278,12 @@ static void SharedPrintfCode(bool append_pid, const char *format, # undef CHECK_NEEDED_LENGTH } RawWrite(buffer); - if (common_flags()->log_to_syslog) - WriteToSyslog(buffer); + + // Remove color sequences from the message. + RemoveANSIEscapeSequencesFromString(buffer); CallPrintfAndReportCallback(buffer); + LogMessageOnPrintf(buffer); + // If we had mapped any memory, clean up. if (buffer != local_buffer) UnmapOrDie((void *)buffer, buffer_size); diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc index 0e97f96331..b6fb7034de 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc @@ -67,7 +67,7 @@ bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, while (IsDecimal(*current_)) current_++; // Qemu may lack the trailing space. - // http://code.google.com/p/address-sanitizer/issues/detail?id=160 + // https://github.com/google/sanitizers/issues/160 // CHECK_EQ(*current_++, ' '); // Skip spaces. while (current_ < next_line && *current_ == ' ') diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cc index 29d699609a..d10881e8a7 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cc @@ -65,7 +65,7 @@ void MemoryMappingLayout::LoadFromCache() { } // Next and NextSegmentLoad were inspired by base/sysinfo.cc in -// Google Perftools, http://code.google.com/p/google-perftools. +// Google Perftools, https://github.com/gperftools/gperftools. // NextSegmentLoad scans the current image for the next segment load command // and returns the start and end addresses and file offset of the corresponding diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc index 80c053164a..7862575b37 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc @@ -118,7 +118,7 @@ void BufferedStackTrace::PopStackFrames(uptr count) { uptr BufferedStackTrace::LocatePcInTrace(uptr pc) { // Use threshold to find PC in stack trace, as PC we want to unwind from may // slightly differ from return address in the actual unwinded stack trace. - const int kPcThreshold = 304; + const int kPcThreshold = 320; for (uptr i = 0; i < size; ++i) { if (MatchPc(pc, trace[i], kPcThreshold)) return i; diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h b/src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h index bf5aa0e7bb..969cedb165 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h @@ -29,7 +29,7 @@ static const u32 kStackTraceMax = 256; // Fast unwind is the only option on Mac for now; we will need to // revisit this macro when slow unwind works on Mac, see -// https://code.google.com/p/address-sanitizer/issues/detail?id=137 +// https://github.com/google/sanitizers/issues/137 #if SANITIZER_MAC # define SANITIZER_CAN_SLOW_UNWIND 0 #else diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc index 6fd63126f0..2376ee56e1 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc @@ -15,7 +15,7 @@ #include "sanitizer_platform.h" #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) || \ - defined(__aarch64__)) + defined(__aarch64__) || defined(__powerpc64__)) #include "sanitizer_stoptheworld.h" @@ -511,5 +511,5 @@ uptr SuspendedThreadsList::RegisterCount() { } } // namespace __sanitizer -#endif // SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) - // || defined(__aarch64__) +#endif // SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) + // || defined(__aarch64__) || defined(__powerpc64__) diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc index 46d4638133..f0f2c9c725 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc @@ -127,7 +127,7 @@ void SuppressionContext::Parse(const char *str) { Printf("%s: failed to parse suppressions\n", SanitizerToolName); Die(); } - Suppression s = {}; + Suppression s; s.type = suppression_types_[type]; s.templ = (char*)InternalAlloc(end2 - line + 1); internal_memcpy(s.templ, line, end2 - line); diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h b/src/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h index 03f6c87261..0ca875a2dd 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h @@ -20,6 +20,7 @@ namespace __sanitizer { struct Suppression { + Suppression() { internal_memset(this, 0, sizeof(*this)); } const char *type; char *templ; atomic_uint32_t hit_count; @@ -42,7 +43,7 @@ class SuppressionContext { void GetMatched(InternalMmapVector *matched); private: - static const int kMaxSuppressionTypes = 16; + static const int kMaxSuppressionTypes = 32; const char **const suppression_types_; const int suppression_types_num_; diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cc index aeaa09b0bd..64048fa7e5 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cc @@ -33,12 +33,18 @@ bool DlAddrSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) { int result = dladdr((const void *)addr, &info); if (!result) return false; const char *demangled = DemangleCXXABI(info.dli_sname); - stack->info.function = internal_strdup(demangled); + stack->info.function = demangled ? internal_strdup(demangled) : nullptr; return true; } -bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *info) { - return false; +bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) { + Dl_info info; + int result = dladdr((const void *)addr, &info); + if (!result) return false; + const char *demangled = DemangleCXXABI(info.dli_sname); + datainfo->name = internal_strdup(demangled); + datainfo->start = (uptr)info.dli_saddr; + return true; } class AtosSymbolizerProcess : public SymbolizerProcess { @@ -90,7 +96,9 @@ static bool IsAtosErrorMessage(const char *str) { return false; } -static bool ParseCommandOutput(const char *str, SymbolizedStack *res) { +static bool ParseCommandOutput(const char *str, uptr addr, char **out_name, + char **out_module, char **out_file, uptr *line, + uptr *start_address) { // Trim ending newlines. char *trim; ExtractTokenUpToDelimiter(str, "\n", &trim); @@ -98,7 +106,9 @@ static bool ParseCommandOutput(const char *str, SymbolizedStack *res) { // The line from `atos` is in one of these formats: // myfunction (in library.dylib) (sourcefile.c:17) // myfunction (in library.dylib) + 0x1fe + // myfunction (in library.dylib) + 15 // 0xdeadbeef (in library.dylib) + 0x1fe + // 0xdeadbeef (in library.dylib) + 15 // 0xdeadbeef (in library.dylib) // 0xdeadbeef @@ -109,21 +119,33 @@ static bool ParseCommandOutput(const char *str, SymbolizedStack *res) { } 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; + char *symbol_name; + rest = ExtractTokenUpToDelimiter(rest, " (in ", &symbol_name); + if (rest[0] == '\0') { + InternalFree(symbol_name); + InternalFree(trim); + return false; + } + + if (internal_strncmp(symbol_name, "0x", 2) != 0) + *out_name = symbol_name; else - InternalFree(function_name); - rest = ExtractTokenUpToDelimiter(rest, ") ", &res->info.module); + InternalFree(symbol_name); + rest = ExtractTokenUpToDelimiter(rest, ") ", out_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); + if (out_file) { + rest++; + rest = ExtractTokenUpToDelimiter(rest, ":", out_file); + char *extracted_line_number; + rest = ExtractTokenUpToDelimiter(rest, ")", &extracted_line_number); + if (line) *line = (uptr)internal_atoll(extracted_line_number); + InternalFree(extracted_line_number); + } + } else if (rest[0] == '+') { + rest += 2; + uptr offset = internal_atoll(rest); + if (start_address) *start_address = addr - offset; } InternalFree(trim); @@ -139,14 +161,29 @@ bool AtosSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) { internal_snprintf(command, sizeof(command), "0x%zx\n", addr); const char *buf = process_->SendCommand(command); if (!buf) return false; - if (!ParseCommandOutput(buf, stack)) { + uptr line; + if (!ParseCommandOutput(buf, addr, &stack->info.function, &stack->info.module, + &stack->info.file, &line, nullptr)) { process_ = nullptr; return false; } + stack->info.line = (int)line; return true; } -bool AtosSymbolizer::SymbolizeData(uptr addr, DataInfo *info) { return false; } +bool AtosSymbolizer::SymbolizeData(uptr addr, DataInfo *info) { + 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, addr, &info->name, &info->module, nullptr, + nullptr, &info->start)) { + process_ = nullptr; + return false; + } + return true; +} } // namespace __sanitizer diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc index a19b0a6786..fc8a7d91ac 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc @@ -75,7 +75,7 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() { #if SANITIZER_MAC fd_t fd = kInvalidFd; // Use forkpty to disable buffering in the new terminal. - pid = forkpty(&fd, 0, 0, 0); + pid = internal_forkpty(&fd); if (pid == -1) { // forkpty() failed. Report("WARNING: failed to fork external symbolizer (errno: %d)\n", @@ -452,10 +452,6 @@ static void ChooseSymbolizerTools(IntrusiveList *list, VReport(2, "Using dladdr symbolizer.\n"); list->push_back(new(*allocator) DlAddrSymbolizer()); #endif // SANITIZER_MAC - - if (list->size() == 0) { - Report("WARNING: no internal or external symbolizer found.\n"); - } } Symbolizer *Symbolizer::PlatformInit() { diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc index ea037159d0..213aced89d 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cc @@ -78,6 +78,15 @@ void DTLS_Destroy() { DTLS_Deallocate(dtls.dtv, s); } +#if defined(__powerpc64__) +// This is glibc's TLS_DTV_OFFSET: +// "Dynamic thread vector pointers point 0x8000 past the start of each +// TLS block." +static const uptr kDtvOffset = 0x8000; +#else +static const uptr kDtvOffset = 0; +#endif + DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res, uptr static_tls_begin, uptr static_tls_end) { if (!common_flags()->intercept_tls_get_addr) return 0; @@ -87,7 +96,7 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res, DTLS_Resize(dso_id + 1); if (dtls.dtv[dso_id].beg) return 0; uptr tls_size = 0; - uptr tls_beg = reinterpret_cast(res) - arg->offset; + uptr tls_beg = reinterpret_cast(res) - arg->offset - kDtvOffset; VPrintf(2, "__tls_get_addr: %p {%p,%p} => %p; tls_beg: %p; sp: %p " "num_live_dtls %zd\n", arg, arg->dso_id, arg->offset, res, tls_beg, &tls_beg, diff --git a/src/compiler-rt/lib/sanitizer_common/sanitizer_win.cc b/src/compiler-rt/lib/sanitizer_common/sanitizer_win.cc index bcebce0b29..861261d840 100644 --- a/src/compiler-rt/lib/sanitizer_common/sanitizer_win.cc +++ b/src/compiler-rt/lib/sanitizer_common/sanitizer_win.cc @@ -83,10 +83,11 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, } #endif // #if !SANITIZER_GO -void *MmapOrDie(uptr size, const char *mem_type) { +void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (rv == 0) - ReportMmapFailureAndDie(size, mem_type, "allocate", GetLastError()); + ReportMmapFailureAndDie(size, mem_type, "allocate", + GetLastError(), raw_report); return rv; } @@ -220,12 +221,14 @@ struct ModuleInfo { uptr end_address; }; +#ifndef SANITIZER_GO int CompareModulesBase(const void *pl, const void *pr) { const ModuleInfo *l = (ModuleInfo *)pl, *r = (ModuleInfo *)pr; if (l->base_address < r->base_address) return -1; return l->base_address > r->base_address; } +#endif } // namespace #ifndef SANITIZER_GO @@ -366,6 +369,7 @@ static uptr GetPreferredBase(const char *modname) { return (uptr)pe_header->ImageBase; } +#ifndef SANITIZER_GO uptr GetListOfModules(LoadedModule *modules, uptr max_modules, string_predicate_t filter) { HANDLE cur_process = GetCurrentProcess(); @@ -434,7 +438,6 @@ uptr GetListOfModules(LoadedModule *modules, uptr max_modules, return count; }; -#ifndef SANITIZER_GO // We can't use atexit() directly at __asan_init time as the CRT is not fully // initialized at this point. Place the functions into a vector and use // atexit() as soon as it is ready for use (i.e. after .CRT$XIC initializers). @@ -759,6 +762,14 @@ void CheckVMASize() { // Do nothing. } +void DisableReexec() { + // No need to re-exec on Windows. +} + +void MaybeReexec() { + // No need to re-exec on Windows. +} + } // namespace __sanitizer #endif // _WIN32 diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc b/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc index c1bb797db2..6fc308ad14 100644 --- a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc +++ b/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc @@ -208,6 +208,30 @@ TEST(SanitizerCommon, StripPathPrefix) { EXPECT_STREQ("file.h", StripPathPrefix("/usr/lib/./file.h", "/usr/lib/")); } +TEST(SanitizerCommon, RemoveANSIEscapeSequencesFromString) { + RemoveANSIEscapeSequencesFromString(nullptr); + const char *buffs[22] = { + "Default", "Default", + "\033[95mLight magenta", "Light magenta", + "\033[30mBlack\033[32mGreen\033[90mGray", "BlackGreenGray", + "\033[106mLight cyan \033[107mWhite ", "Light cyan White ", + "\033[31mHello\033[0m World", "Hello World", + "\033[38;5;82mHello \033[38;5;198mWorld", "Hello World", + "123[653456789012", "123[653456789012", + "Normal \033[5mBlink \033[25mNormal", "Normal Blink Normal", + "\033[106m\033[107m", "", + "", "", + " ", " ", + }; + + for (size_t i = 0; i < ARRAY_SIZE(buffs); i+=2) { + char *buffer_copy = internal_strdup(buffs[i]); + RemoveANSIEscapeSequencesFromString(buffer_copy); + EXPECT_STREQ(buffer_copy, buffs[i+1]); + InternalFree(buffer_copy); + } +} + TEST(SanitizerCommon, InternalScopedString) { InternalScopedString str(10); EXPECT_EQ(0U, str.length()); diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cc b/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cc index c0230ec6a7..015e32a09e 100644 --- a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cc +++ b/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cc @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// // Tests for sanitizer_libc.h. //===----------------------------------------------------------------------===// +#include #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" @@ -15,7 +16,9 @@ #include "gtest/gtest.h" #if SANITIZER_WINDOWS +#define NOMINMAX #include +#undef NOMINMAX #endif #if SANITIZER_POSIX # include @@ -145,12 +148,65 @@ TEST(SanitizerCommon, FileOps) { #endif } +static const size_t kStrlcpyBufSize = 8; +void test_internal_strlcpy(char *dbuf, const char *sbuf) { + uptr retval = 0; + retval = internal_strlcpy(dbuf, sbuf, kStrlcpyBufSize); + EXPECT_EQ(internal_strncmp(dbuf, sbuf, kStrlcpyBufSize - 1), 0); + EXPECT_EQ(internal_strlen(dbuf), + std::min(internal_strlen(sbuf), (uptr)(kStrlcpyBufSize - 1))); + EXPECT_EQ(retval, internal_strlen(sbuf)); + + // Test with shorter maxlen. + uptr maxlen = 2; + if (internal_strlen(sbuf) > maxlen) { + retval = internal_strlcpy(dbuf, sbuf, maxlen); + EXPECT_EQ(internal_strncmp(dbuf, sbuf, maxlen - 1), 0); + EXPECT_EQ(internal_strlen(dbuf), maxlen - 1); + } +} + TEST(SanitizerCommon, InternalStrFunctions) { const char *haystack = "haystack"; EXPECT_EQ(haystack + 2, internal_strchr(haystack, 'y')); EXPECT_EQ(haystack + 2, internal_strchrnul(haystack, 'y')); EXPECT_EQ(0, internal_strchr(haystack, 'z')); EXPECT_EQ(haystack + 8, internal_strchrnul(haystack, 'z')); + + char dbuf[kStrlcpyBufSize] = {}; + const char *samesizestr = "1234567"; + const char *shortstr = "123"; + const char *longerstr = "123456789"; + + // Test internal_strlcpy. + internal_strlcpy(dbuf, shortstr, 0); + EXPECT_EQ(dbuf[0], 0); + EXPECT_EQ(dbuf[0], 0); + test_internal_strlcpy(dbuf, samesizestr); + test_internal_strlcpy(dbuf, shortstr); + test_internal_strlcpy(dbuf, longerstr); + + // Test internal_strlcat. + char dcatbuf[kStrlcpyBufSize] = {}; + uptr retval = 0; + retval = internal_strlcat(dcatbuf, "aaa", 0); + EXPECT_EQ(internal_strlen(dcatbuf), (uptr)0); + EXPECT_EQ(retval, (uptr)3); + + retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize); + EXPECT_EQ(internal_strcmp(dcatbuf, "123"), 0); + EXPECT_EQ(internal_strlen(dcatbuf), (uptr)3); + EXPECT_EQ(retval, (uptr)3); + + retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize); + EXPECT_EQ(internal_strcmp(dcatbuf, "123123"), 0); + EXPECT_EQ(internal_strlen(dcatbuf), (uptr)6); + EXPECT_EQ(retval, (uptr)6); + + retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize); + EXPECT_EQ(internal_strcmp(dcatbuf, "1231231"), 0); + EXPECT_EQ(internal_strlen(dcatbuf), (uptr)7); + EXPECT_EQ(retval, (uptr)9); } // FIXME: File manipulations are not yet supported on Windows diff --git a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc b/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc index 654ea1db82..3d57eded94 100644 --- a/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc +++ b/src/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc @@ -82,7 +82,7 @@ TEST_F(FastUnwindTest, Basic) { } } -// From: http://code.google.com/p/address-sanitizer/issues/detail?id=162 +// From: https://github.com/google/sanitizers/issues/162 TEST_F(FastUnwindTest, FramePointerLoop) { // Make one fp point to itself. fake_stack[4] = (uhwptr)&fake_stack[4]; diff --git a/src/compiler-rt/lib/tsan/.clang-format b/src/compiler-rt/lib/tsan/.clang-format new file mode 100644 index 0000000000..f6cb8ad931 --- /dev/null +++ b/src/compiler-rt/lib/tsan/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: Google diff --git a/src/compiler-rt/lib/tsan/CMakeLists.txt b/src/compiler-rt/lib/tsan/CMakeLists.txt index cbfca5ce28..c185cfa164 100644 --- a/src/compiler-rt/lib/tsan/CMakeLists.txt +++ b/src/compiler-rt/lib/tsan/CMakeLists.txt @@ -8,13 +8,19 @@ set(TSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS}) append_list_if(COMPILER_RT_HAS_FPIE_FLAG -fPIE TSAN_CFLAGS) append_no_rtti_flag(TSAN_CFLAGS) +if(COMPILER_RT_TSAN_DEBUG_OUTPUT) + # Add extra debug information to TSan runtime. This configuration is rarely + # used, but we need to support it so that debug output will not bitrot. + list(APPEND TSAN_CFLAGS -DTSAN_COLLECT_STATS=1 + -DTSAN_DEBUG_OUTPUT=2) +endif() + set(TSAN_RTL_CFLAGS ${TSAN_CFLAGS}) append_list_if(COMPILER_RT_HAS_MSSE3_FLAG -msse3 TSAN_RTL_CFLAGS) append_list_if(SANITIZER_LIMIT_FRAME_SIZE -Wframe-larger-than=512 TSAN_RTL_CFLAGS) append_list_if(COMPILER_RT_HAS_WGLOBAL_CONSTRUCTORS_FLAG -Wglobal-constructors TSAN_RTL_CFLAGS) -# FIXME: Add support for --sysroot=. compile flag: set(TSAN_SOURCES rtl/tsan_clock.cc @@ -47,6 +53,8 @@ set(TSAN_CXX_SOURCES if(APPLE) list(APPEND TSAN_SOURCES + rtl/tsan_interceptors_mac.cc + rtl/tsan_libdispatch_mac.cc rtl/tsan_platform_mac.cc rtl/tsan_platform_posix.cc) elseif(UNIX) @@ -88,17 +96,40 @@ set(TSAN_RUNTIME_LIBRARIES) add_custom_target(tsan) if(APPLE) + set(TSAN_ASM_SOURCES rtl/tsan_rtl_amd64.S) + # Xcode will try to compile this file as C ('clang -x c'), and that will fail. + if (${CMAKE_GENERATOR} STREQUAL "Xcode") + enable_language(ASM) + else() + # Pass ASM file directly to the C++ compiler. + set_source_files_properties(${TSAN_ASM_SOURCES} PROPERTIES LANGUAGE C) + endif() add_compiler_rt_runtime(clang_rt.tsan SHARED OS ${TSAN_SUPPORTED_OS} ARCHS ${TSAN_SUPPORTED_ARCH} - SOURCES ${TSAN_SOURCES} ${TSAN_CXX_SOURCES} + SOURCES ${TSAN_SOURCES} ${TSAN_CXX_SOURCES} ${TSAN_ASM_SOURCES} OBJECT_LIBS RTInterception RTSanitizerCommon RTSanitizerCommonLibc RTUbsan CFLAGS ${TSAN_RTL_CFLAGS} PARENT_TARGET tsan) + add_compiler_rt_object_libraries(RTTsan_dynamic + OS ${TSAN_SUPPORTED_OS} + ARCHS ${TSAN_SUPPORTED_ARCH} + SOURCES ${TSAN_SOURCES} ${TSAN_CXX_SOURCES} ${TSAN_ASM_SOURCES} + CFLAGS ${TSAN_RTL_CFLAGS}) + + # Build and check Go runtime. + set(BUILDGO_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/go/buildgo.sh) + add_custom_target(GotsanRuntimeCheck + COMMAND env "CC=${CMAKE_C_COMPILER} ${OSX_SYSROOT_FLAG}" + IN_TMPDIR=1 SILENT=1 ${BUILDGO_SCRIPT} + DEPENDS tsan ${BUILDGO_SCRIPT} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go + COMMENT "Checking TSan Go runtime..." + VERBATIM) else() foreach(arch ${TSAN_SUPPORTED_ARCH}) if(arch STREQUAL "x86_64") @@ -115,6 +146,16 @@ else() WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go COMMENT "Checking TSan Go runtime..." VERBATIM) + elseif(arch STREQUAL "aarch64") + set(TSAN_ASM_SOURCES rtl/tsan_rtl_aarch64.S) + # Pass ASM file directly to the C++ compiler. + set_source_files_properties(${TSAN_ASM_SOURCES} PROPERTIES + LANGUAGE C) + elseif(arch MATCHES "powerpc64|powerpc64le") + set(TSAN_ASM_SOURCES rtl/tsan_rtl_ppc64.S) + # Pass ASM file directly to the C++ compiler. + set_source_files_properties(${TSAN_ASM_SOURCES} PROPERTIES + LANGUAGE C) else() set(TSAN_ASM_SOURCES) endif() @@ -150,13 +191,30 @@ endif() add_dependencies(compiler-rt tsan) +# Make sure that non-platform-specific files don't include any system headers. +if(COMPILER_RT_HAS_SYSROOT_FLAG) + file(GLOB _tsan_generic_sources rtl/tsan*) + file(GLOB _tsan_platform_sources rtl/tsan*posix* rtl/tsan*mac* + rtl/tsan*linux*) + list(REMOVE_ITEM _tsan_generic_sources ${_tsan_platform_sources}) + set_source_files_properties(${_tsan_generic_sources} + PROPERTIES COMPILE_FLAGS "--sysroot=.") +endif() + # Build libcxx instrumented with TSan. if(COMPILER_RT_HAS_LIBCXX_SOURCES AND COMPILER_RT_TEST_COMPILER_ID STREQUAL "Clang") - set(LIBCXX_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libcxx_tsan) - add_custom_libcxx(libcxx_tsan ${LIBCXX_PREFIX} - DEPS ${TSAN_RUNTIME_LIBRARIES} - CFLAGS -fsanitize=thread) + set(libcxx_tsan_deps) + foreach(arch ${TSAN_SUPPORTED_ARCH}) + get_target_flags_for_arch(${arch} TARGET_CFLAGS) + set(LIBCXX_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libcxx_tsan_${arch}) + add_custom_libcxx(libcxx_tsan_${arch} ${LIBCXX_PREFIX} + DEPS ${TSAN_RUNTIME_LIBRARIES} + CFLAGS ${TARGET_CFLAGS} -fsanitize=thread) + list(APPEND libcxx_tsan_deps libcxx_tsan_${arch}) + endforeach() + + add_custom_target(libcxx_tsan DEPENDS ${libcxx_tsan_deps}) endif() if(COMPILER_RT_INCLUDE_TESTS) diff --git a/src/compiler-rt/lib/tsan/Makefile.old b/src/compiler-rt/lib/tsan/Makefile.old deleted file mode 100644 index b2ac912d74..0000000000 --- a/src/compiler-rt/lib/tsan/Makefile.old +++ /dev/null @@ -1,109 +0,0 @@ -DEBUG=0 -LDFLAGS=-ldl -lrt -lpthread -pie -CXXFLAGS = -std=c++11 -fPIE -fno-rtti -g -Wall -Werror \ - -DGTEST_HAS_RTTI=0 -DSANITIZER_DEBUG=$(DEBUG) \ - -DTSAN_CONTAINS_UBSAN=0 -CLANG=clang -FILECHECK=FileCheck -# Silence warnings that Clang produces for gtest code. -# Use -Wno-attributes so that gcc doesn't complain about unknown warning types. -CXXFLAGS += -Wno-attributes -ifeq ($(DEBUG), 0) - CXXFLAGS += -O3 -endif -ifeq ($(CXX), $(CLANG)++) - CXXFLAGS += -Wno-unused-private-field -Wno-static-in-inline -Wgnu -else - CXXFLAGS += -Wno-maybe-uninitialized -endif - -LIBTSAN=rtl/libtsan.a -GTEST_ROOT=third_party/googletest -GTEST_INCLUDE=-I$(GTEST_ROOT)/include -GTEST_BUILD_DIR=$(GTEST_ROOT)/build -GTEST_LIB_NAME=gtest-all.o -GTEST_LIB=$(GTEST_BUILD_DIR)/$(GTEST_LIB_NAME) - -SANITIZER_TESTS_PATH=../sanitizer_common/tests -SANITIZER_COMMON_TESTS_SRC=$(wildcard $(SANITIZER_TESTS_PATH)/*_test.cc) -SANITIZER_COMMON_EXCLUDED_TESTS=$(SANITIZER_TESTS_PATH)/sanitizer_nolibc_test.cc -SANITIZER_COMMON_GOOD_TESTS=$(filter-out $(SANITIZER_COMMON_EXCLUDED_TESTS), $(SANITIZER_COMMON_TESTS_SRC)) -SANITIZER_COMMON_TESTS_OBJ=$(patsubst %.cc,%.o,$(SANITIZER_COMMON_GOOD_TESTS)) -RTL_TEST_SRC=$(wildcard tests/rtl/*.cc) -RTL_TEST_OBJ=$(patsubst %.cc,%.o,$(RTL_TEST_SRC)) -UNIT_TEST_SRC=$(wildcard tests/unit/*_test.cc) -UNIT_TEST_OBJ=$(patsubst %.cc,%.o,$(UNIT_TEST_SRC)) -UNIT_TEST_HDR=$(wildcard rtl/*.h) $(wildcard ../sanitizer_common/*.h) -LIT_TESTS_PATH=../../test/tsan - -INCLUDES=-Irtl -I.. -I../../include $(GTEST_INCLUDE) - -all: libtsan test - -help: - @ echo "A little help is always welcome!" - @ echo "The most useful targets are:" - @ echo " make install_deps # Install third-party dependencies required for building" - @ echo " make presubmit # Run it every time before committing" - @ echo - @ echo "For more info, see http://code.google.com/p/thread-sanitizer/wiki/Development" - -$(LIBTSAN): libtsan - -libtsan: - $(MAKE) -C rtl -f Makefile.old DEBUG=$(DEBUG) - -%.o: %.cc $(UNIT_TEST_HDR) $(LIBTSAN) - $(CXX) $(CXXFLAGS) $(CFLAGS) $(INCLUDES) -o $@ -c $< - -tsan_test: $(UNIT_TEST_OBJ) $(RTL_TEST_OBJ) \ - $(SANITIZER_COMMON_TESTS_OBJ) $(LIBTSAN) $(GTEST_LIB) - $(CXX) -Wl,--whole-archive $^ -Wl,--no-whole-archive -o $@ $(LDFLAGS) - -test: libtsan tsan_test - -run: all - (ulimit -s 8192; ./tsan_test) - CC=$(CLANG) CXX=$(CLANG)++ FILECHECK=$(FILECHECK) $(LIT_TESTS_PATH)/test_output.sh - -presubmit: - ../sanitizer_common/scripts/check_lint.sh - # Debug build with clang. - $(MAKE) -f Makefile.old clean - $(MAKE) -f Makefile.old run DEBUG=1 -j 16 CC=$(CLANG) CXX=$(CLANG)++ - # Release build with clang. - $(MAKE) -f Makefile.old clean - $(MAKE) -f Makefile.old run DEBUG=0 -j 16 CC=$(CLANG) CXX=$(CLANG)++ - ./check_memcpy.sh - # Debug build with gcc - $(MAKE) -f Makefile.old clean - $(MAKE) -f Makefile.old run DEBUG=1 -j 16 CC=gcc CXX=g++ - # Release build with gcc - $(MAKE) -f Makefile.old clean - $(MAKE) -f Makefile.old run DEBUG=0 -j 16 CC=gcc CXX=g++ - ./check_memcpy.sh - ./check_analyze.sh - # Sanity check for Go runtime - (cd go && ./buildgo.sh) - # Check cmake build - ./check_cmake.sh - @ echo PRESUBMIT PASSED - -install_deps: - rm -rf third_party - mkdir third_party - (cd third_party && \ - svn co -r613 http://googletest.googlecode.com/svn/trunk googletest \ - ) - -$(GTEST_LIB): - mkdir -p $(GTEST_BUILD_DIR) && \ - cd $(GTEST_BUILD_DIR) && \ - $(MAKE) -f ../make/Makefile CXXFLAGS="$(CXXFLAGS)" CFLAGS="$(CFLAGS)" CC=$(CC) CXX=$(CXX) $(GTEST_LIB_NAME) - -clean: - rm -f asm_*.s libtsan.nm libtsan.objdump */*.o tsan_test - rm -rf $(GTEST_BUILD_DIR) - $(MAKE) clean -C rtl -f Makefile.old - rm -f go/*.s - rm -rf build diff --git a/src/compiler-rt/lib/tsan/analyze_libtsan.sh b/src/compiler-rt/lib/tsan/analyze_libtsan.sh index 705e4c5460..ae29f1b5b0 100755 --- a/src/compiler-rt/lib/tsan/analyze_libtsan.sh +++ b/src/compiler-rt/lib/tsan/analyze_libtsan.sh @@ -1,10 +1,17 @@ #!/bin/bash +# +# Script that prints information about generated code in TSan runtime. set -e set -u +if [[ "$#" != 1 ]]; then + echo "Usage: $0 /path/to/binary/built/with/tsan" + exit 1 +fi + get_asm() { - grep __tsan_$1.: -A 10000 libtsan.objdump | \ + grep __tsan_$1.: -A 10000 ${OBJDUMP_CONTENTS} | \ awk "/[^:]$/ {print;} />:/ {c++; if (c == 2) {exit}}" } @@ -19,15 +26,19 @@ list="write1 \ func_entry \ func_exit" -BIN=`dirname $0`/tsan_test -objdump -d $BIN > libtsan.objdump -nm -S $BIN | grep "__tsan_" > libtsan.nm +BIN=$1 +OUTPUT_DIR=$(mktemp -t -d analyze_libtsan_out.XXXXXXXX) +OBJDUMP_CONTENTS=${OUTPUT_DIR}/libtsan_objdump +NM_CONTENTS=${OUTPUT_DIR}/libtsan_nm + +objdump -d $BIN > ${OBJDUMP_CONTENTS} +nm -S $BIN | grep "__tsan_" > ${NM_CONTENTS} for f in $list; do - file=asm_$f.s + file=${OUTPUT_DIR}/asm_$f.s get_asm $f > $file tot=$(wc -l < $file) - size=$(grep __tsan_$f$ libtsan.nm | awk --non-decimal-data '{print ("0x"$2)+0}') + size=$(grep __tsan_$f$ ${NM_CONTENTS} | awk --non-decimal-data '{print ("0x"$2)+0}') rsp=$(grep '(%rsp)' $file | wc -l) push=$(grep 'push' $file | wc -l) pop=$(grep 'pop' $file | wc -l) diff --git a/src/compiler-rt/lib/tsan/check_analyze.sh b/src/compiler-rt/lib/tsan/check_analyze.sh index 4b33393ef6..0f6cc06984 100755 --- a/src/compiler-rt/lib/tsan/check_analyze.sh +++ b/src/compiler-rt/lib/tsan/check_analyze.sh @@ -1,7 +1,17 @@ #!/bin/bash +# +# Script that checks that critical functions in TSan runtime have correct number +# of push/pop/rsp instructions to verify that runtime is efficient enough. + set -u -RES=$(./analyze_libtsan.sh) +if [[ "$#" != 1 ]]; then + echo "Usage: $0 /path/to/binary/built/with/tsan" + exit 1 +fi + +SCRIPTDIR=$(dirname $0) +RES=$(${SCRIPTDIR}/analyze_libtsan.sh $1) PrintRes() { printf "%s\n" "$RES" } @@ -22,7 +32,13 @@ for f in write1; do check $f pop 2 done -for f in write2 write4 write8; do +for f in write2 write4; do + check $f rsp 1 + check $f push 4 + check $f pop 4 +done + +for f in write8; do check $f rsp 1 check $f push 3 check $f pop 3 diff --git a/src/compiler-rt/lib/tsan/check_memcpy.sh b/src/compiler-rt/lib/tsan/check_memcpy.sh deleted file mode 100755 index 101df1166b..0000000000 --- a/src/compiler-rt/lib/tsan/check_memcpy.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -# Ensure that tsan runtime does not contain compiler-emitted memcpy and memset calls. - -set -eu - -ROOTDIR=$(dirname $0) -TEST_DIR=$ROOTDIR/../../test/tsan - -: ${CXX:=clang++} -CFLAGS="-fsanitize=thread -fPIE -O1 -g" -LDFLAGS="-pie -lpthread -ldl -lrt -lm -Wl,--whole-archive $ROOTDIR/rtl/libtsan.a -Wl,--no-whole-archive" - -SRC=$TEST_DIR/simple_race.cc -OBJ=$SRC.o -EXE=$SRC.exe -$CXX $SRC $CFLAGS -c -o $OBJ -$CXX $OBJ $LDFLAGS -o $EXE - -NCALL=$(objdump -d $EXE | egrep "callq .*<__interceptor_mem(cpy|set)>" | wc -l) -if [ "$NCALL" != "0" ]; then - echo FAIL: found $NCALL memcpy/memset calls - exit 1 -fi - -# tail calls -NCALL=$(objdump -d $EXE | egrep "jmpq .*<__interceptor_mem(cpy|set)>" | wc -l) -if [ "$NCALL" != "0" ]; then - echo FAIL: found $NCALL memcpy/memset calls - exit 1 -fi diff --git a/src/compiler-rt/lib/tsan/go/buildgo.sh b/src/compiler-rt/lib/tsan/go/buildgo.sh index a7e12f18c3..668530c5f4 100755 --- a/src/compiler-rt/lib/tsan/go/buildgo.sh +++ b/src/compiler-rt/lib/tsan/go/buildgo.sh @@ -20,6 +20,7 @@ SRCS=" ../rtl/tsan_sync.cc ../../sanitizer_common/sanitizer_allocator.cc ../../sanitizer_common/sanitizer_common.cc + ../../sanitizer_common/sanitizer_common_libcdep.cc ../../sanitizer_common/sanitizer_deadlock_detector2.cc ../../sanitizer_common/sanitizer_flag_parser.cc ../../sanitizer_common/sanitizer_flags.cc @@ -36,7 +37,7 @@ SRCS=" if [ "`uname -a | grep Linux`" != "" ]; then SUFFIX="linux_amd64" OSCFLAGS="-fPIC -ffreestanding -Wno-maybe-uninitialized -Wno-unused-const-variable -Werror -Wno-unknown-warning-option" - OSLDFLAGS="-lpthread -lrt -fPIC -fpie" + OSLDFLAGS="-lpthread -fPIC -fpie" SRCS=" $SRCS ../rtl/tsan_platform_linux.cc @@ -49,19 +50,20 @@ if [ "`uname -a | grep Linux`" != "" ]; then ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc " elif [ "`uname -a | grep FreeBSD`" != "" ]; then - SUFFIX="freebsd_amd64" - OSCFLAGS="-fno-strict-aliasing -fPIC -Werror" - OSLDFLAGS="-lpthread -fPIC -fpie" - SRCS=" - $SRCS - ../rtl/tsan_platform_linux.cc - ../../sanitizer_common/sanitizer_posix.cc - ../../sanitizer_common/sanitizer_posix_libcdep.cc - ../../sanitizer_common/sanitizer_procmaps_common.cc - ../../sanitizer_common/sanitizer_procmaps_freebsd.cc - ../../sanitizer_common/sanitizer_linux.cc - ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc - " + SUFFIX="freebsd_amd64" + OSCFLAGS="-fno-strict-aliasing -fPIC -Werror" + OSLDFLAGS="-lpthread -fPIC -fpie" + SRCS=" + $SRCS + ../rtl/tsan_platform_linux.cc + ../../sanitizer_common/sanitizer_posix.cc + ../../sanitizer_common/sanitizer_posix_libcdep.cc + ../../sanitizer_common/sanitizer_procmaps_common.cc + ../../sanitizer_common/sanitizer_procmaps_freebsd.cc + ../../sanitizer_common/sanitizer_linux.cc + ../../sanitizer_common/sanitizer_linux_libcdep.cc + ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc + " elif [ "`uname -a | grep Darwin`" != "" ]; then SUFFIX="darwin_amd64" OSCFLAGS="-fPIC -Wno-unused-const-variable -Wno-unknown-warning-option" diff --git a/src/compiler-rt/lib/tsan/rtl/Makefile.old b/src/compiler-rt/lib/tsan/rtl/Makefile.old deleted file mode 100644 index 0ef6fed370..0000000000 --- a/src/compiler-rt/lib/tsan/rtl/Makefile.old +++ /dev/null @@ -1,63 +0,0 @@ -CXXFLAGS = -std=c++11 -fPIE -g -Wall -Werror -fno-builtin -msse3 -DSANITIZER_DEBUG=$(DEBUG) -DTSAN_CONTAINS_UBSAN=0 -CLANG=clang -ifeq ($(DEBUG), 0) - CXXFLAGS += -O3 -endif - -# For interception. FIXME: move interception one level higher. -INTERCEPTION=../../interception -COMMON=../../sanitizer_common -INCLUDES= -I../.. -I../../../include -EXTRA_CXXFLAGS=-fno-exceptions -fno-rtti -NO_SYSROOT=--sysroot=. -CXXFLAGS+=$(EXTRA_CXXFLAGS) -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 - -ifeq ($(CXX), $(CLANG)++) - # Global constructors are banned. - CXXFLAGS+=-Wglobal-constructors -endif - - - -all: libtsan.a - -LIBTSAN_HEADERS=$(wildcard *.h) \ - $(wildcard $(INTERCEPTION)/*.h) \ - $(wildcard $(COMMON)/*.h) -LIBTSAN_SRC=$(wildcard *.cc) -LIBTSAN_ASM_SRC=$(wildcard *.S) -INTERCEPTION_SRC=$(wildcard $(INTERCEPTION)/*.cc) -COMMON_SRC=$(filter-out $(wildcard $(COMMON)/*_nolibc.cc),$(wildcard $(COMMON)/*.cc)) - -LIBTSAN_OBJ=$(patsubst %.cc,%.o,$(LIBTSAN_SRC)) \ - $(patsubst %.S,%.o,$(LIBTSAN_ASM_SRC)) \ - $(patsubst $(INTERCEPTION)/%.cc,%.o,$(INTERCEPTION_SRC)) \ - $(patsubst $(COMMON)/%.cc,%.o,$(COMMON_SRC)) - -%_linux.o: %_linux.cc Makefile.old $(LIBTSAN_HEADERS) - $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -%.o: %.cc Makefile.old $(LIBTSAN_HEADERS) - $(CXX) $(CXXFLAGS) $(INCLUDES) $(NO_SYSROOT) -c $< -%.o: $(INTERCEPTION)/%.cc Makefile.old $(LIBTSAN_HEADERS) - $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ -%.o: $(COMMON)/%.cc Makefile.old $(LIBTSAN_HEADERS) - $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ -%.o: %.S - $(CXX) $(INCLUDES) -o $@ -c $< - -libtsan.a: $(LIBTSAN_OBJ) - ar ru $@ $(LIBTSAN_OBJ) - -libtsan_dummy.a: tsan_dummy_rtl.o - ar ru $@ $< - -clean: - rm -f *.o *.a diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_defs.h b/src/compiler-rt/lib/tsan/rtl/tsan_defs.h index 385e366c39..9c7b329dcf 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_defs.h +++ b/src/compiler-rt/lib/tsan/rtl/tsan_defs.h @@ -38,13 +38,10 @@ namespace __tsan { const bool kGoMode = true; const bool kCppMode = false; const char *const kTsanOptionsEnv = "GORACE"; -// Go linker does not support weak symbols. -#define CPP_WEAK #else const bool kGoMode = false; const bool kCppMode = true; const char *const kTsanOptionsEnv = "TSAN_OPTIONS"; -#define CPP_WEAK WEAK #endif const int kTidBits = 13; diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h b/src/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h index a1cf84b8f1..e9815c90a9 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h +++ b/src/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h @@ -108,7 +108,7 @@ class DenseSlabAlloc { // Reserve 0 as invalid index. IndexT start = fillpos_ == 0 ? 1 : 0; for (IndexT i = start; i < kL2Size; i++) { - new(batch + i) T(); + new(batch + i) T; *(IndexT*)(batch + i) = i + 1 + fillpos_ * kL2Size; } *(IndexT*)(batch + kL2Size - 1) = 0; diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_flags.cc b/src/compiler-rt/lib/tsan/rtl/tsan_flags.cc index b8bee70b7f..761523171c 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_flags.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_flags.cc @@ -29,8 +29,8 @@ Flags *flags() { #ifdef TSAN_EXTERNAL_HOOKS extern "C" const char* __tsan_default_options(); #else -extern "C" SANITIZER_INTERFACE_ATTRIBUTE -const char *WEAK __tsan_default_options() { +SANITIZER_WEAK_DEFAULT_IMPL +const char *__tsan_default_options() { return ""; } #endif @@ -61,9 +61,13 @@ void InitializeFlags(Flags *f, const char *env) { CommonFlags cf; cf.CopyFrom(*common_flags()); cf.allow_addr2line = true; -#ifndef SANITIZER_GO - cf.detect_deadlocks = true; -#endif + if (kGoMode) { + // Does not work as expected for Go: runtime handles SIGABRT and crashes. + cf.abort_on_error = false; + // Go does not have mutexes. + } else { + cf.detect_deadlocks = true; + } cf.print_suppressions = false; cf.stack_trace_format = " #%n %f %S %M"; cf.exitcode = 66; diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index 800c7bd98b..7c835c6dc7 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -48,6 +48,13 @@ using namespace __tsan; // NOLINT #define __libc_realloc REAL(realloc) #define __libc_calloc REAL(calloc) #define __libc_free REAL(free) +#elif SANITIZER_ANDROID +#define __errno_location __errno +#define __libc_malloc REAL(malloc) +#define __libc_realloc REAL(realloc) +#define __libc_calloc REAL(calloc) +#define __libc_free REAL(free) +#define mallopt(a, b) #endif #if SANITIZER_LINUX || SANITIZER_FREEBSD @@ -79,9 +86,11 @@ struct ucontext_t { }; #endif -#if defined(__x86_64__) || defined(__mips__) +#if defined(__x86_64__) || defined(__mips__) \ + || (defined(__powerpc64__) && defined(__BIG_ENDIAN__)) #define PTHREAD_ABI_BASE "GLIBC_2.3.2" -#elif defined(__aarch64__) +#elif defined(__aarch64__) || (defined(__powerpc64__) \ + && defined(__LITTLE_ENDIAN__)) #define PTHREAD_ABI_BASE "GLIBC_2.17" #endif @@ -103,10 +112,12 @@ extern "C" void *pthread_self(); extern "C" void _exit(int status); extern "C" int *__errno_location(); extern "C" int fileno_unlocked(void *stream); +#if !SANITIZER_ANDROID extern "C" void *__libc_calloc(uptr size, uptr n); extern "C" void *__libc_realloc(void *ptr, uptr size); +#endif extern "C" int dirfd(void *dirp); -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_ANDROID extern "C" int mallopt(int param, int value); #endif extern __sanitizer_FILE *stdout, *stderr; @@ -124,7 +135,7 @@ const int SIGFPE = 8; const int SIGSEGV = 11; const int SIGPIPE = 13; const int SIGTERM = 15; -#ifdef __mips__ +#if defined(__mips__) || SANITIZER_MAC const int SIGBUS = 10; const int SIGSYS = 12; #else @@ -149,6 +160,17 @@ typedef long long_t; // NOLINT typedef void (*sighandler_t)(int sig); typedef void (*sigactionhandler_t)(int sig, my_siginfo_t *siginfo, void *uctx); +#if SANITIZER_ANDROID +struct sigaction_t { + u32 sa_flags; + union { + sighandler_t sa_handler; + sigactionhandler_t sa_sgiaction; + }; + __sanitizer_sigset_t sa_mask; + void (*sa_restorer)(); +}; +#else struct sigaction_t { #ifdef __mips__ u32 sa_flags; @@ -160,6 +182,9 @@ struct sigaction_t { #if SANITIZER_FREEBSD int sa_flags; __sanitizer_sigset_t sa_mask; +#elif SANITIZER_MAC + __sanitizer_sigset_t sa_mask; + int sa_flags; #else __sanitizer_sigset_t sa_mask; #ifndef __mips__ @@ -168,11 +193,12 @@ struct sigaction_t { void (*sa_restorer)(); #endif }; +#endif const sighandler_t SIG_DFL = (sighandler_t)0; const sighandler_t SIG_IGN = (sighandler_t)1; const sighandler_t SIG_ERR = (sighandler_t)-1; -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC const int SA_SIGINFO = 0x40; const int SIG_SETMASK = 3; #elif defined(__mips__) @@ -201,6 +227,9 @@ struct ThreadSignalContext { atomic_uintptr_t in_blocking_func; atomic_uintptr_t have_pending_signals; SignalDesc pending_signals[kSigCount]; + // emptyset and oldset are too big for stack. + __sanitizer_sigset_t emptyset; + __sanitizer_sigset_t oldset; }; // The object is 64-byte aligned, because we want hot data to be located in @@ -233,7 +262,9 @@ static ThreadSignalContext *SigCtx(ThreadState *thr) { return ctx; } +#if !SANITIZER_MAC static unsigned g_thread_finalize_key; +#endif ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc) @@ -264,17 +295,20 @@ ScopedInterceptor::~ScopedInterceptor() { } } -#define SCOPED_TSAN_INTERCEPTOR(func, ...) \ - SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \ - if (REAL(func) == 0) { \ - Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \ - Die(); \ - } \ - if (thr->ignore_interceptors || thr->in_ignored_lib) \ - return REAL(func)(__VA_ARGS__); \ -/**/ +void ScopedInterceptor::UserCallbackStart() { + if (in_ignored_lib_) { + thr_->in_ignored_lib = false; + ThreadIgnoreEnd(thr_, pc_); + } +} + +void ScopedInterceptor::UserCallbackEnd() { + if (in_ignored_lib_) { + thr_->in_ignored_lib = true; + ThreadIgnoreBegin(thr_, pc_); + } +} -#define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__) #define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func) #if SANITIZER_FREEBSD # define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func) @@ -359,6 +393,7 @@ static void at_exit_wrapper(void *arg) { static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(), void *arg, void *dso); +#if !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, atexit, void (*f)()) { if (cur_thread()->in_symbolizer) return 0; @@ -367,6 +402,7 @@ TSAN_INTERCEPTOR(int, atexit, void (*f)()) { SCOPED_INTERCEPTOR_RAW(atexit, f); return setup_at_exit_wrapper(thr, pc, (void(*)())f, 0, 0); } +#endif TSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) { if (cur_thread()->in_symbolizer) @@ -422,7 +458,7 @@ static void JmpBufGarbageCollect(ThreadState *thr, uptr sp) { JmpBuf *buf = &thr->jmp_bufs[i]; if (buf->sp <= sp) { uptr sz = thr->jmp_bufs.Size(); - thr->jmp_bufs[i] = thr->jmp_bufs[sz - 1]; + internal_memcpy(buf, &thr->jmp_bufs[sz - 1], sizeof(*buf)); thr->jmp_bufs.PopBack(); i--; } @@ -449,11 +485,17 @@ static void SetJmp(ThreadState *thr, uptr sp, uptr mangled_sp) { } static void LongJmp(ThreadState *thr, uptr *env) { -#if SANITIZER_FREEBSD +#ifdef __powerpc__ + uptr mangled_sp = env[0]; +#elif SANITIZER_FREEBSD || SANITIZER_MAC uptr mangled_sp = env[2]; -#else +#elif defined(SANITIZER_LINUX) +# ifdef __aarch64__ + uptr mangled_sp = env[13]; +# else uptr mangled_sp = env[6]; -#endif // SANITIZER_FREEBSD +# endif +#endif // Find the saved buf by mangled_sp. for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) { JmpBuf *buf = &thr->jmp_bufs[i]; @@ -483,6 +525,11 @@ extern "C" void __tsan_setjmp(uptr sp, uptr mangled_sp) { SetJmp(cur_thread(), sp, mangled_sp); } +#if SANITIZER_MAC +TSAN_INTERCEPTOR(int, setjmp, void *env); +TSAN_INTERCEPTOR(int, _setjmp, void *env); +TSAN_INTERCEPTOR(int, sigsetjmp, void *env); +#else // SANITIZER_MAC // Not called. Merely to satisfy TSAN_INTERCEPT(). extern "C" SANITIZER_INTERFACE_ATTRIBUTE int __interceptor_setjmp(void *env); @@ -521,6 +568,7 @@ DEFINE_REAL(int, setjmp, void *env) DEFINE_REAL(int, _setjmp, void *env) DEFINE_REAL(int, sigsetjmp, void *env) DEFINE_REAL(int, __sigsetjmp, void *env) +#endif // SANITIZER_MAC TSAN_INTERCEPTOR(void, longjmp, uptr *env, int val) { { @@ -791,8 +839,25 @@ TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) { } #endif +// __cxa_guard_acquire and friends need to be intercepted in a special way - +// regular interceptors will break statically-linked libstdc++. Linux +// interceptors are especially defined as weak functions (so that they don't +// cause link errors when user defines them as well). So they silently +// auto-disable themselves when such symbol is already present in the binary. If +// we link libstdc++ statically, it will bring own __cxa_guard_acquire which +// will silently replace our interceptor. That's why on Linux we simply export +// these interceptors with INTERFACE_ATTRIBUTE. +// On OS X, we don't support statically linking, so we just use a regular +// interceptor. +#if SANITIZER_MAC +#define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR +#else +#define STDCXX_INTERCEPTOR(rettype, name, ...) \ + extern "C" rettype INTERFACE_ATTRIBUTE name(__VA_ARGS__) +#endif + // Used in thread-safe function static initialization. -extern "C" int INTERFACE_ATTRIBUTE __cxa_guard_acquire(atomic_uint32_t *g) { +STDCXX_INTERCEPTOR(int, __cxa_guard_acquire, atomic_uint32_t *g) { SCOPED_INTERCEPTOR_RAW(__cxa_guard_acquire, g); for (;;) { u32 cmp = atomic_load(g, memory_order_acquire); @@ -808,13 +873,13 @@ extern "C" int INTERFACE_ATTRIBUTE __cxa_guard_acquire(atomic_uint32_t *g) { } } -extern "C" void INTERFACE_ATTRIBUTE __cxa_guard_release(atomic_uint32_t *g) { +STDCXX_INTERCEPTOR(void, __cxa_guard_release, atomic_uint32_t *g) { SCOPED_INTERCEPTOR_RAW(__cxa_guard_release, g); Release(thr, pc, (uptr)g); atomic_store(g, 1, memory_order_release); } -extern "C" void INTERFACE_ATTRIBUTE __cxa_guard_abort(atomic_uint32_t *g) { +STDCXX_INTERCEPTOR(void, __cxa_guard_abort, atomic_uint32_t *g) { SCOPED_INTERCEPTOR_RAW(__cxa_guard_abort, g); atomic_store(g, 0, memory_order_relaxed); } @@ -832,6 +897,7 @@ void DestroyThreadState() { } } // namespace __tsan +#if !SANITIZER_MAC static void thread_finalize(void *v) { uptr iter = (uptr)v; if (iter > 1) { @@ -843,6 +909,7 @@ static void thread_finalize(void *v) { } DestroyThreadState(); } +#endif struct ThreadParam { @@ -860,6 +927,7 @@ extern "C" void *__tsan_thread_start_func(void *arg) { ThreadState *thr = cur_thread(); // Thread-local state is not initialized yet. ScopedIgnoreInterceptors ignore; +#if !SANITIZER_MAC ThreadIgnoreBegin(thr, 0); if (pthread_setspecific(g_thread_finalize_key, (void *)GetPthreadDestructorIterations())) { @@ -867,6 +935,7 @@ extern "C" void *__tsan_thread_start_func(void *arg) { Die(); } ThreadIgnoreEnd(thr, 0); +#endif while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0) internal_sched_yield(); ThreadStart(thr, tid, GetTid()); @@ -1325,7 +1394,7 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { return 0; } -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1337,7 +1406,7 @@ TSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { #endif TSAN_INTERCEPTOR(int, stat, const char *path, void *buf) { -#if SANITIZER_FREEBSD || SANITIZER_MAC +#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_ANDROID SCOPED_TSAN_INTERCEPTOR(stat, path, buf); READ_STRING(thr, pc, path, 0); return REAL(stat)(path, buf); @@ -1348,7 +1417,7 @@ TSAN_INTERCEPTOR(int, stat, const char *path, void *buf) { #endif } -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat64, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1359,7 +1428,7 @@ TSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT___XSTAT64 #endif -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__xstat64, 0, path, buf); READ_STRING(thr, pc, path, 0); @@ -1370,7 +1439,7 @@ TSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT_STAT64 #endif -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1382,7 +1451,7 @@ TSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) { #endif TSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) { -#if SANITIZER_FREEBSD || SANITIZER_MAC +#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_ANDROID SCOPED_TSAN_INTERCEPTOR(lstat, path, buf); READ_STRING(thr, pc, path, 0); return REAL(lstat)(path, buf); @@ -1393,7 +1462,7 @@ TSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) { #endif } -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat64, version, path, buf); READ_STRING(thr, pc, path, 0); @@ -1404,7 +1473,7 @@ TSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT___LXSTAT64 #endif -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) { SCOPED_TSAN_INTERCEPTOR(__lxstat64, 0, path, buf); READ_STRING(thr, pc, path, 0); @@ -1415,7 +1484,7 @@ TSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) { #define TSAN_MAYBE_INTERCEPT_LSTAT64 #endif -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf); if (fd > 0) @@ -1428,7 +1497,7 @@ TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { #endif TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { -#if SANITIZER_FREEBSD || SANITIZER_MAC +#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_ANDROID SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf); if (fd > 0) FdAccess(thr, pc, fd); @@ -1441,7 +1510,7 @@ TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { #endif } -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); if (fd > 0) @@ -1453,7 +1522,7 @@ TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { #define TSAN_MAYBE_INTERCEPT___FXSTAT64 #endif -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) { SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf); if (fd > 0) @@ -1678,7 +1747,7 @@ TSAN_INTERCEPTOR(int, __close, int fd) { #endif // glibc guts -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) { SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr); int fds[64]; @@ -1823,8 +1892,10 @@ TSAN_INTERCEPTOR(int, rmdir, char *path) { TSAN_INTERCEPTOR(int, closedir, void *dirp) { SCOPED_TSAN_INTERCEPTOR(closedir, dirp); - int fd = dirfd(dirp); - FdClose(thr, pc, fd); + if (dirp) { + int fd = dirfd(dirp); + FdClose(thr, pc, fd); + } return REAL(closedir)(dirp); } @@ -1910,10 +1981,8 @@ void ProcessPendingSignals(ThreadState *thr) { return; atomic_store(&sctx->have_pending_signals, 0, memory_order_relaxed); atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed); - // These are too big for stack. - static THREADLOCAL __sanitizer_sigset_t emptyset, oldset; - CHECK_EQ(0, REAL(sigfillset)(&emptyset)); - CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &emptyset, &oldset)); + CHECK_EQ(0, REAL(sigfillset)(&sctx->emptyset)); + CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sctx->emptyset, &sctx->oldset)); for (int sig = 0; sig < kSigCount; sig++) { SignalDesc *signal = &sctx->pending_signals[sig]; if (signal->armed) { @@ -1922,7 +1991,7 @@ void ProcessPendingSignals(ThreadState *thr) { &signal->siginfo, &signal->ctx); } } - CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &oldset, 0)); + CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sctx->oldset, 0)); atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed); } @@ -2011,7 +2080,7 @@ TSAN_INTERCEPTOR(int, sigaction, int sig, sigaction_t *act, sigaction_t *old) { sigactions[sig].sa_flags = *(volatile int*)&act->sa_flags; internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask, sizeof(sigactions[sig].sa_mask)); -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC sigactions[sig].sa_restorer = act->sa_restorer; #endif sigaction_t newact; @@ -2144,7 +2213,7 @@ TSAN_INTERCEPTOR(int, vfork, int fake) { return WRAP(fork)(fake); } -#if !SANITIZER_MAC +#if !SANITIZER_MAC && !SANITIZER_ANDROID typedef int (*dl_iterate_phdr_cb_t)(__sanitizer_dl_phdr_info *info, SIZE_T size, void *data); struct dl_iterate_phdr_data { @@ -2466,7 +2535,7 @@ static void finalize(void *arg) { Die(); } -#if !SANITIZER_MAC +#if !SANITIZER_MAC && !SANITIZER_ANDROID static void unreachable() { Report("FATAL: ThreadSanitizer: unreachable called\n"); Die(); @@ -2631,12 +2700,14 @@ void InitializeInterceptors() { TSAN_INTERCEPT(fork); TSAN_INTERCEPT(vfork); +#if !SANITIZER_ANDROID TSAN_INTERCEPT(dl_iterate_phdr); +#endif TSAN_INTERCEPT(on_exit); TSAN_INTERCEPT(__cxa_atexit); TSAN_INTERCEPT(_exit); -#if !SANITIZER_MAC +#if !SANITIZER_MAC && !SANITIZER_ANDROID // Need to setup it, because interceptors check that the function is resolved. // But atexit is emitted directly into the module, so can't be resolved. REAL(atexit) = (int(*)(void(*)()))unreachable; @@ -2647,12 +2718,50 @@ void InitializeInterceptors() { Die(); } +#if !SANITIZER_MAC if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) { Printf("ThreadSanitizer: failed to create thread key\n"); Die(); } +#endif FdInit(); } } // namespace __tsan + +// Invisible barrier for tests. +// There were several unsuccessful iterations for this functionality: +// 1. Initially it was implemented in user code using +// REAL(pthread_barrier_wait). But pthread_barrier_wait is not supported on +// MacOS. Futexes are linux-specific for this matter. +// 2. Then we switched to atomics+usleep(10). But usleep produced parasitic +// "as-if synchronized via sleep" messages in reports which failed some +// output tests. +// 3. Then we switched to atomics+sched_yield. But this produced tons of tsan- +// visible events, which lead to "failed to restore stack trace" failures. +// Note that no_sanitize_thread attribute does not turn off atomic interception +// so attaching it to the function defined in user code does not help. +// That's why we now have what we have. +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void __tsan_testonly_barrier_init(u64 *barrier, u32 count) { + if (count >= (1 << 8)) { + Printf("barrier_init: count is too large (%d)\n", count); + Die(); + } + // 8 lsb is thread count, the remaining are count of entered threads. + *barrier = count; +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void __tsan_testonly_barrier_wait(u64 *barrier) { + unsigned old = __atomic_fetch_add(barrier, 1 << 8, __ATOMIC_RELAXED); + unsigned old_epoch = (old >> 8) / (old & 0xff); + for (;;) { + unsigned cur = __atomic_load_n(barrier, __ATOMIC_RELAXED); + unsigned cur_epoch = (cur >> 8) / (cur & 0xff); + if (cur_epoch != old_epoch) + return; + internal_sched_yield(); + } +} diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.h b/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.h index 49b79a7c5f..d831620cfa 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.h +++ b/src/compiler-rt/lib/tsan/rtl/tsan_interceptors.h @@ -10,6 +10,8 @@ class ScopedInterceptor { public: ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc); ~ScopedInterceptor(); + void UserCallbackStart(); + void UserCallbackEnd(); private: ThreadState *const thr_; const uptr pc_; @@ -26,6 +28,24 @@ class ScopedInterceptor { (void)pc; \ /**/ +#define SCOPED_TSAN_INTERCEPTOR(func, ...) \ + SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \ + if (REAL(func) == 0) { \ + Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \ + Die(); \ + } \ + if (thr->ignore_interceptors || thr->in_ignored_lib) \ + return REAL(func)(__VA_ARGS__); \ +/**/ + +#define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START() \ + si.UserCallbackStart(); + +#define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END() \ + si.UserCallbackEnd(); + +#define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__) + #if SANITIZER_FREEBSD #define __libc_free __free #define __libc_malloc __malloc diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc b/src/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc new file mode 100644 index 0000000000..2bf7ad9861 --- /dev/null +++ b/src/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cc @@ -0,0 +1,91 @@ +//===-- tsan_interceptors_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 a part of ThreadSanitizer (TSan), a race detector. +// +// Mac-specific interceptors. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if SANITIZER_MAC + +#include "interception/interception.h" +#include "tsan_interceptors.h" + +#include + +namespace __tsan { + +TSAN_INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) { + CHECK(!cur_thread()->is_dead); + if (!cur_thread()->is_inited) { + return REAL(OSSpinLockLock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(OSSpinLockLock, lock); + REAL(OSSpinLockLock)(lock); + Acquire(thr, pc, (uptr)lock); +} + +TSAN_INTERCEPTOR(bool, OSSpinLockTry, volatile OSSpinLock *lock) { + CHECK(!cur_thread()->is_dead); + if (!cur_thread()->is_inited) { + return REAL(OSSpinLockTry)(lock); + } + SCOPED_TSAN_INTERCEPTOR(OSSpinLockTry, lock); + bool result = REAL(OSSpinLockTry)(lock); + if (result) + Acquire(thr, pc, (uptr)lock); + return result; +} + +TSAN_INTERCEPTOR(void, OSSpinLockUnlock, volatile OSSpinLock *lock) { + CHECK(!cur_thread()->is_dead); + if (!cur_thread()->is_inited) { + return REAL(OSSpinLockUnlock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(OSSpinLockUnlock, lock); + Release(thr, pc, (uptr)lock); + REAL(OSSpinLockUnlock)(lock); +} + +TSAN_INTERCEPTOR(void, os_lock_lock, void *lock) { + CHECK(!cur_thread()->is_dead); + if (!cur_thread()->is_inited) { + return REAL(os_lock_lock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(os_lock_lock, lock); + REAL(os_lock_lock)(lock); + Acquire(thr, pc, (uptr)lock); +} + +TSAN_INTERCEPTOR(bool, os_lock_trylock, void *lock) { + CHECK(!cur_thread()->is_dead); + if (!cur_thread()->is_inited) { + return REAL(os_lock_trylock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(os_lock_trylock, lock); + bool result = REAL(os_lock_trylock)(lock); + if (result) + Acquire(thr, pc, (uptr)lock); + return result; +} + +TSAN_INTERCEPTOR(void, os_lock_unlock, void *lock) { + CHECK(!cur_thread()->is_dead); + if (!cur_thread()->is_inited) { + return REAL(os_lock_unlock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(os_lock_unlock, lock); + Release(thr, pc, (uptr)lock); + REAL(os_lock_unlock)(lock); +} + +} // namespace __tsan + +#endif // SANITIZER_MAC diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc b/src/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc new file mode 100644 index 0000000000..617dc91b33 --- /dev/null +++ b/src/compiler-rt/lib/tsan/rtl/tsan_libdispatch_mac.cc @@ -0,0 +1,284 @@ +//===-- tsan_libdispatch_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 a part of ThreadSanitizer (TSan), a race detector. +// +// Mac-specific libdispatch (GCD) support. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if SANITIZER_MAC + +#include "sanitizer_common/sanitizer_common.h" +#include "interception/interception.h" +#include "tsan_interceptors.h" +#include "tsan_platform.h" +#include "tsan_rtl.h" + +#include +#include +#include + +typedef long long_t; // NOLINT + +namespace __tsan { + +typedef struct { + dispatch_queue_t queue; + void *orig_context; + dispatch_function_t orig_work; + uptr object_to_acquire; + dispatch_object_t object_to_release; +} tsan_block_context_t; + +// The offsets of different fields of the dispatch_queue_t structure, exported +// by libdispatch.dylib. +extern "C" struct dispatch_queue_offsets_s { + const uint16_t dqo_version; + const uint16_t dqo_label; + const uint16_t dqo_label_size; + const uint16_t dqo_flags; + const uint16_t dqo_flags_size; + const uint16_t dqo_serialnum; + const uint16_t dqo_serialnum_size; + const uint16_t dqo_width; + const uint16_t dqo_width_size; + const uint16_t dqo_running; + const uint16_t dqo_running_size; + const uint16_t dqo_suspend_cnt; + const uint16_t dqo_suspend_cnt_size; + const uint16_t dqo_target_queue; + const uint16_t dqo_target_queue_size; + const uint16_t dqo_priority; + const uint16_t dqo_priority_size; +} dispatch_queue_offsets; + +static bool IsQueueSerial(dispatch_queue_t q) { + CHECK_EQ(dispatch_queue_offsets.dqo_width_size, 2); + uptr width = *(uint16_t *)(((uptr)q) + dispatch_queue_offsets.dqo_width); + CHECK_NE(width, 0); + return width == 1; +} + +static tsan_block_context_t *AllocContext(ThreadState *thr, uptr pc, + dispatch_queue_t queue, + void *orig_context, + dispatch_function_t orig_work) { + tsan_block_context_t *new_context = + (tsan_block_context_t *)user_alloc(thr, pc, sizeof(tsan_block_context_t)); + new_context->queue = queue; + new_context->orig_context = orig_context; + new_context->orig_work = orig_work; + new_context->object_to_acquire = (uptr)new_context; + new_context->object_to_release = nullptr; + return new_context; +} + +static void dispatch_callback_wrap_acquire(void *param) { + SCOPED_INTERCEPTOR_RAW(dispatch_async_f_callback_wrap); + tsan_block_context_t *context = (tsan_block_context_t *)param; + Acquire(thr, pc, context->object_to_acquire); + + // Extra retain/release is required for dispatch groups. We use the group + // itself to synchronize, but in a notification (dispatch_group_notify + // callback), it may be disposed already. To solve this, we retain the group + // and release it here. + if (context->object_to_release) dispatch_release(context->object_to_release); + + // In serial queues, work items can be executed on different threads, we need + // to explicitly synchronize on the queue itself. + if (IsQueueSerial(context->queue)) Acquire(thr, pc, (uptr)context->queue); + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); + context->orig_work(context->orig_context); + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); + if (IsQueueSerial(context->queue)) Release(thr, pc, (uptr)context->queue); + user_free(thr, pc, context); +} + +static void invoke_and_release_block(void *param) { + dispatch_block_t block = (dispatch_block_t)param; + block(); + Block_release(block); +} + +#define DISPATCH_INTERCEPT_B(name) \ + TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, dispatch_block_t block) { \ + SCOPED_TSAN_INTERCEPTOR(name, q, block); \ + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); \ + dispatch_block_t heap_block = Block_copy(block); \ + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); \ + tsan_block_context_t *new_context = \ + AllocContext(thr, pc, q, heap_block, &invoke_and_release_block); \ + Release(thr, pc, (uptr)new_context); \ + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); \ + REAL(name##_f)(q, new_context, dispatch_callback_wrap_acquire); \ + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); \ + } + +#define DISPATCH_INTERCEPT_F(name) \ + TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, void *context, \ + dispatch_function_t work) { \ + SCOPED_TSAN_INTERCEPTOR(name, q, context, work); \ + tsan_block_context_t *new_context = \ + AllocContext(thr, pc, q, context, work); \ + Release(thr, pc, (uptr)new_context); \ + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); \ + REAL(name)(q, new_context, dispatch_callback_wrap_acquire); \ + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); \ + } + +// We wrap dispatch_async, dispatch_sync and friends where we allocate a new +// context, which is used to synchronize (we release the context before +// submitting, and the callback acquires it before executing the original +// callback). +DISPATCH_INTERCEPT_B(dispatch_async) +DISPATCH_INTERCEPT_B(dispatch_barrier_async) +DISPATCH_INTERCEPT_F(dispatch_async_f) +DISPATCH_INTERCEPT_F(dispatch_barrier_async_f) +DISPATCH_INTERCEPT_B(dispatch_sync) +DISPATCH_INTERCEPT_B(dispatch_barrier_sync) +DISPATCH_INTERCEPT_F(dispatch_sync_f) +DISPATCH_INTERCEPT_F(dispatch_barrier_sync_f) + +// GCD's dispatch_once implementation has a fast path that contains a racy read +// and it's inlined into user's code. Furthermore, this fast path doesn't +// establish a proper happens-before relations between the initialization and +// code following the call to dispatch_once. We could deal with this in +// instrumented code, but there's not much we can do about it in system +// libraries. Let's disable the fast path (by never storing the value ~0 to +// predicate), so the interceptor is always called, and let's add proper release +// and acquire semantics. Since TSan does not see its own atomic stores, the +// race on predicate won't be reported - the only accesses to it that TSan sees +// are the loads on the fast path. Loads don't race. Secondly, dispatch_once is +// both a macro and a real function, we want to intercept the function, so we +// need to undefine the macro. +#undef dispatch_once +TSAN_INTERCEPTOR(void, dispatch_once, dispatch_once_t *predicate, + dispatch_block_t block) { + SCOPED_TSAN_INTERCEPTOR(dispatch_once, predicate, block); + atomic_uint32_t *a = reinterpret_cast(predicate); + u32 v = atomic_load(a, memory_order_acquire); + if (v == 0 && + atomic_compare_exchange_strong(a, &v, 1, memory_order_relaxed)) { + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); + block(); + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); + Release(thr, pc, (uptr)a); + atomic_store(a, 2, memory_order_release); + } else { + while (v != 2) { + internal_sched_yield(); + v = atomic_load(a, memory_order_acquire); + } + Acquire(thr, pc, (uptr)a); + } +} + +#undef dispatch_once_f +TSAN_INTERCEPTOR(void, dispatch_once_f, dispatch_once_t *predicate, + void *context, dispatch_function_t function) { + SCOPED_TSAN_INTERCEPTOR(dispatch_once_f, predicate, context, function); + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); + WRAP(dispatch_once)(predicate, ^(void) { + function(context); + }); + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); +} + +TSAN_INTERCEPTOR(long_t, dispatch_semaphore_signal, + dispatch_semaphore_t dsema) { + SCOPED_TSAN_INTERCEPTOR(dispatch_semaphore_signal, dsema); + Release(thr, pc, (uptr)dsema); + return REAL(dispatch_semaphore_signal)(dsema); +} + +TSAN_INTERCEPTOR(long_t, dispatch_semaphore_wait, dispatch_semaphore_t dsema, + dispatch_time_t timeout) { + SCOPED_TSAN_INTERCEPTOR(dispatch_semaphore_wait, dsema, timeout); + long_t result = REAL(dispatch_semaphore_wait)(dsema, timeout); + if (result == 0) Acquire(thr, pc, (uptr)dsema); + return result; +} + +TSAN_INTERCEPTOR(long_t, dispatch_group_wait, dispatch_group_t group, + dispatch_time_t timeout) { + SCOPED_TSAN_INTERCEPTOR(dispatch_group_wait, group, timeout); + long_t result = REAL(dispatch_group_wait)(group, timeout); + if (result == 0) Acquire(thr, pc, (uptr)group); + return result; +} + +TSAN_INTERCEPTOR(void, dispatch_group_leave, dispatch_group_t group) { + SCOPED_TSAN_INTERCEPTOR(dispatch_group_leave, group); + Release(thr, pc, (uptr)group); + REAL(dispatch_group_leave)(group); +} + +TSAN_INTERCEPTOR(void, dispatch_group_async, dispatch_group_t group, + dispatch_queue_t queue, dispatch_block_t block) { + SCOPED_TSAN_INTERCEPTOR(dispatch_group_async, group, queue, block); + dispatch_retain(group); + dispatch_group_enter(group); + WRAP(dispatch_async)(queue, ^(void) { + block(); + WRAP(dispatch_group_leave)(group); + dispatch_release(group); + }); +} + +TSAN_INTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group, + dispatch_queue_t queue, void *context, + dispatch_function_t work) { + SCOPED_TSAN_INTERCEPTOR(dispatch_group_async_f, group, queue, context, work); + dispatch_retain(group); + dispatch_group_enter(group); + WRAP(dispatch_async)(queue, ^(void) { + work(context); + WRAP(dispatch_group_leave)(group); + dispatch_release(group); + }); +} + +TSAN_INTERCEPTOR(void, dispatch_group_notify, dispatch_group_t group, + dispatch_queue_t q, dispatch_block_t block) { + SCOPED_TSAN_INTERCEPTOR(dispatch_group_notify, group, q, block); + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); + dispatch_block_t heap_block = Block_copy(block); + SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); + tsan_block_context_t *new_context = + AllocContext(thr, pc, q, heap_block, &invoke_and_release_block); + new_context->object_to_acquire = (uptr)group; + + // Will be released in dispatch_callback_wrap_acquire. + new_context->object_to_release = group; + dispatch_retain(group); + + Release(thr, pc, (uptr)group); + REAL(dispatch_group_notify_f)(group, q, new_context, + dispatch_callback_wrap_acquire); +} + +TSAN_INTERCEPTOR(void, dispatch_group_notify_f, dispatch_group_t group, + dispatch_queue_t q, void *context, dispatch_function_t work) { + SCOPED_TSAN_INTERCEPTOR(dispatch_group_notify_f, group, q, context, work); + tsan_block_context_t *new_context = AllocContext(thr, pc, q, context, work); + new_context->object_to_acquire = (uptr)group; + + // Will be released in dispatch_callback_wrap_acquire. + new_context->object_to_release = group; + dispatch_retain(group); + + Release(thr, pc, (uptr)group); + REAL(dispatch_group_notify_f)(group, q, new_context, + dispatch_callback_wrap_acquire); +} + +} // namespace __tsan + +#endif // SANITIZER_MAC diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_malloc_mac.cc b/src/compiler-rt/lib/tsan/rtl/tsan_malloc_mac.cc index 6319fdf603..7fd94273c3 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_malloc_mac.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_malloc_mac.cc @@ -28,30 +28,36 @@ using namespace __tsan; void *p = \ user_alloc(cur_thread(), StackTrace::GetCurrentPc(), size, alignment) #define COMMON_MALLOC_MALLOC(size) \ + if (cur_thread()->in_symbolizer) \ + return REAL(malloc)(size); \ SCOPED_INTERCEPTOR_RAW(malloc, size); \ void *p = user_alloc(thr, pc, size) -#define COMMON_MALLOC_REALLOC(ptr, size) \ +#define COMMON_MALLOC_REALLOC(ptr, size) \ + if (cur_thread()->in_symbolizer) \ + return REAL(realloc)(ptr, size); \ SCOPED_INTERCEPTOR_RAW(realloc, ptr, size); \ - void *p = user_realloc(thr, pc, ptr, size); -#define COMMON_MALLOC_CALLOC(count, size) \ + void *p = user_realloc(thr, pc, ptr, size) +#define COMMON_MALLOC_CALLOC(count, size) \ + if (cur_thread()->in_symbolizer) \ + return REAL(calloc)(count, size); \ SCOPED_INTERCEPTOR_RAW(calloc, size, count); \ - void *p = user_calloc(thr, pc, size, count); -#define COMMON_MALLOC_VALLOC(size) \ - SCOPED_INTERCEPTOR_RAW(valloc, size); \ - void *p = user_alloc(thr, pc, size, GetPageSizeCached()); -#define COMMON_MALLOC_FREE(ptr) \ + void *p = user_calloc(thr, pc, size, count) +#define COMMON_MALLOC_VALLOC(size) \ + if (cur_thread()->in_symbolizer) \ + return REAL(valloc)(size); \ + SCOPED_INTERCEPTOR_RAW(valloc, size); \ + void *p = user_alloc(thr, pc, size, GetPageSizeCached()) +#define COMMON_MALLOC_FREE(ptr) \ + if (cur_thread()->in_symbolizer) \ + return REAL(free)(ptr); \ SCOPED_INTERCEPTOR_RAW(free, ptr); \ - user_free(thr, pc, ptr); + user_free(thr, pc, ptr) #define COMMON_MALLOC_SIZE(ptr) \ uptr size = user_alloc_usable_size(ptr); #define COMMON_MALLOC_FILL_STATS(zone, stats) #define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \ (void)zone_name; \ Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", ptr); -#define COMMON_MALLOC_IGNORE_INVALID_FREE false -#define COMMON_MALLOC_REPORT_FREE_UNALLOCATED(ptr, zone_ptr, zone_name) \ - (void)zone_name; \ - Report("free_common(%p) -- attempting to free unallocated memory.\n", ptr); #define COMMON_MALLOC_NAMESPACE __tsan #include "sanitizer_common/sanitizer_malloc_mac.inc" diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_mman.cc b/src/compiler-rt/lib/tsan/rtl/tsan_mman.cc index 3168226b9c..7247c6e000 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_mman.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_mman.cc @@ -19,12 +19,14 @@ #include "tsan_flags.h" // May be overriden by front-end. -extern "C" void WEAK __sanitizer_malloc_hook(void *ptr, uptr size) { +SANITIZER_WEAK_DEFAULT_IMPL +void __sanitizer_malloc_hook(void *ptr, uptr size) { (void)ptr; (void)size; } -extern "C" void WEAK __sanitizer_free_hook(void *ptr) { +SANITIZER_WEAK_DEFAULT_IMPL +void __sanitizer_free_hook(void *ptr) { (void)ptr; } diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_new_delete.cc b/src/compiler-rt/lib/tsan/rtl/tsan_new_delete.cc index 18ba9082c4..ebb422cf20 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_new_delete.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_new_delete.cc @@ -11,8 +11,8 @@ // // Interceptors for operators new and delete. //===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_internal_defs.h" #include "interception/interception.h" +#include "sanitizer_common/sanitizer_internal_defs.h" #include "tsan_interceptors.h" using namespace __tsan; // NOLINT @@ -23,7 +23,7 @@ struct nothrow_t {}; DECLARE_REAL(void *, malloc, uptr size) DECLARE_REAL(void, free, void *ptr) -#if SANITIZER_MAC +#if SANITIZER_MAC || SANITIZER_ANDROID #define __libc_malloc REAL(malloc) #define __libc_free REAL(free) #endif diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_platform.h b/src/compiler-rt/lib/tsan/rtl/tsan_platform.h index 57cd86d830..c2b4871553 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_platform.h +++ b/src/compiler-rt/lib/tsan/rtl/tsan_platform.h @@ -41,21 +41,23 @@ C/C++ on linux/x86_64 and freebsd/x86_64 7e00 0000 0000 - 7e80 0000 0000: - 7e80 0000 0000 - 8000 0000 0000: modules and main thread stack */ -const uptr kMetaShadowBeg = 0x300000000000ull; -const uptr kMetaShadowEnd = 0x400000000000ull; -const uptr kTraceMemBeg = 0x600000000000ull; -const uptr kTraceMemEnd = 0x620000000000ull; -const uptr kShadowBeg = 0x020000000000ull; -const uptr kShadowEnd = 0x100000000000ull; -const uptr kHeapMemBeg = 0x7d0000000000ull; -const uptr kHeapMemEnd = 0x7e0000000000ull; -const uptr kLoAppMemBeg = 0x000000001000ull; -const uptr kLoAppMemEnd = 0x010000000000ull; -const uptr kHiAppMemBeg = 0x7e8000000000ull; -const uptr kHiAppMemEnd = 0x800000000000ull; -const uptr kAppMemMsk = 0x7c0000000000ull; -const uptr kAppMemXor = 0x020000000000ull; -const uptr kVdsoBeg = 0xf000000000000000ull; +struct Mapping { + static const uptr kMetaShadowBeg = 0x300000000000ull; + static const uptr kMetaShadowEnd = 0x400000000000ull; + static const uptr kTraceMemBeg = 0x600000000000ull; + static const uptr kTraceMemEnd = 0x620000000000ull; + static const uptr kShadowBeg = 0x020000000000ull; + static const uptr kShadowEnd = 0x100000000000ull; + static const uptr kHeapMemBeg = 0x7d0000000000ull; + static const uptr kHeapMemEnd = 0x7e0000000000ull; + static const uptr kLoAppMemBeg = 0x000000001000ull; + static const uptr kLoAppMemEnd = 0x010000000000ull; + static const uptr kHiAppMemBeg = 0x7e8000000000ull; + static const uptr kHiAppMemEnd = 0x800000000000ull; + static const uptr kAppMemMsk = 0x7c0000000000ull; + static const uptr kAppMemXor = 0x020000000000ull; + static const uptr kVdsoBeg = 0xf000000000000000ull; +}; #elif defined(__mips64) /* C/C++ on linux/mips64 @@ -71,128 +73,181 @@ fe00 0000 00 - ff00 0000 00: heap ff00 0000 00 - ff80 0000 00: - ff80 0000 00 - ffff ffff ff: modules and main thread stack */ -const uptr kMetaShadowBeg = 0x3000000000ull; -const uptr kMetaShadowEnd = 0x4000000000ull; -const uptr kTraceMemBeg = 0x6000000000ull; -const uptr kTraceMemEnd = 0x6200000000ull; -const uptr kShadowBeg = 0x1400000000ull; -const uptr kShadowEnd = 0x2400000000ull; -const uptr kHeapMemBeg = 0xfe00000000ull; -const uptr kHeapMemEnd = 0xff00000000ull; -const uptr kLoAppMemBeg = 0x0100000000ull; -const uptr kLoAppMemEnd = 0x0200000000ull; -const uptr kHiAppMemBeg = 0xff80000000ull; -const uptr kHiAppMemEnd = 0xffffffffffull; -const uptr kAppMemMsk = 0xfc00000000ull; -const uptr kAppMemXor = 0x0400000000ull; -const uptr kVdsoBeg = 0xfffff00000ull; +struct Mapping { + static const uptr kMetaShadowBeg = 0x3000000000ull; + static const uptr kMetaShadowEnd = 0x4000000000ull; + static const uptr kTraceMemBeg = 0x6000000000ull; + static const uptr kTraceMemEnd = 0x6200000000ull; + static const uptr kShadowBeg = 0x1400000000ull; + static const uptr kShadowEnd = 0x2400000000ull; + static const uptr kHeapMemBeg = 0xfe00000000ull; + static const uptr kHeapMemEnd = 0xff00000000ull; + static const uptr kLoAppMemBeg = 0x0100000000ull; + static const uptr kLoAppMemEnd = 0x0200000000ull; + static const uptr kHiAppMemBeg = 0xff80000000ull; + static const uptr kHiAppMemEnd = 0xffffffffffull; + static const uptr kAppMemMsk = 0xfc00000000ull; + static const uptr kAppMemXor = 0x0400000000ull; + static const uptr kVdsoBeg = 0xfffff00000ull; +}; #elif defined(__aarch64__) -# if SANITIZER_AARCH64_VMA == 39 +// AArch64 supports multiple VMA which leads to multiple address transformation +// functions. To support these multiple VMAS transformations and mappings TSAN +// runtime for AArch64 uses an external memory read (vmaSize) to select which +// mapping to use. Although slower, it make a same instrumented binary run on +// multiple kernels. + /* C/C++ on linux/aarch64 (39-bit VMA) -0000 4000 00 - 0200 0000 00: main binary -2000 0000 00 - 4000 0000 00: shadow memory -4000 0000 00 - 5000 0000 00: metainfo -5000 0000 00 - 6000 0000 00: - +0000 0010 00 - 0100 0000 00: main binary +0100 0000 00 - 0800 0000 00: - +0800 0000 00 - 2000 0000 00: shadow memory +2000 0000 00 - 3100 0000 00: - +3100 0000 00 - 3400 0000 00: metainfo +3400 0000 00 - 5500 0000 00: - +5500 0000 00 - 5600 0000 00: main binary (PIE) +5600 0000 00 - 6000 0000 00: - 6000 0000 00 - 6200 0000 00: traces 6200 0000 00 - 7d00 0000 00: - -7d00 0000 00 - 7e00 0000 00: heap -7e00 0000 00 - 7fff ffff ff: modules and main thread stack +7c00 0000 00 - 7d00 0000 00: heap +7d00 0000 00 - 7fff ffff ff: modules and main thread stack */ -const uptr kLoAppMemBeg = 0x0000400000ull; -const uptr kLoAppMemEnd = 0x0200000000ull; -const uptr kShadowBeg = 0x2000000000ull; -const uptr kShadowEnd = 0x4000000000ull; -const uptr kMetaShadowBeg = 0x4000000000ull; -const uptr kMetaShadowEnd = 0x5000000000ull; -const uptr kTraceMemBeg = 0x6000000000ull; -const uptr kTraceMemEnd = 0x6200000000ull; -const uptr kHeapMemBeg = 0x7d00000000ull; -const uptr kHeapMemEnd = 0x7e00000000ull; -const uptr kHiAppMemBeg = 0x7e00000000ull; -const uptr kHiAppMemEnd = 0x7fffffffffull; -const uptr kAppMemMsk = 0x7800000000ull; -const uptr kAppMemXor = 0x0800000000ull; -const uptr kVdsoBeg = 0x7f00000000ull; -# elif SANITIZER_AARCH64_VMA == 42 +struct Mapping39 { + static const uptr kLoAppMemBeg = 0x0000001000ull; + static const uptr kLoAppMemEnd = 0x0100000000ull; + static const uptr kShadowBeg = 0x0800000000ull; + static const uptr kShadowEnd = 0x2000000000ull; + static const uptr kMetaShadowBeg = 0x3100000000ull; + static const uptr kMetaShadowEnd = 0x3400000000ull; + static const uptr kMidAppMemBeg = 0x5500000000ull; + static const uptr kMidAppMemEnd = 0x5600000000ull; + static const uptr kMidShadowOff = 0x5000000000ull; + static const uptr kTraceMemBeg = 0x6000000000ull; + static const uptr kTraceMemEnd = 0x6200000000ull; + static const uptr kHeapMemBeg = 0x7c00000000ull; + static const uptr kHeapMemEnd = 0x7d00000000ull; + static const uptr kHiAppMemBeg = 0x7e00000000ull; + static const uptr kHiAppMemEnd = 0x7fffffffffull; + static const uptr kAppMemMsk = 0x7800000000ull; + static const uptr kAppMemXor = 0x0200000000ull; + static const uptr kVdsoBeg = 0x7f00000000ull; +}; + /* C/C++ on linux/aarch64 (42-bit VMA) -00000 4000 00 - 01000 0000 00: main binary +00000 0010 00 - 01000 0000 00: main binary 01000 0000 00 - 10000 0000 00: - 10000 0000 00 - 20000 0000 00: shadow memory 20000 0000 00 - 26000 0000 00: - 26000 0000 00 - 28000 0000 00: metainfo -28000 0000 00 - 36200 0000 00: - +28000 0000 00 - 2aa00 0000 00: - +2aa00 0000 00 - 2ab00 0000 00: main binary (PIE) +2ab00 0000 00 - 36200 0000 00: - 36200 0000 00 - 36240 0000 00: traces 36240 0000 00 - 3e000 0000 00: - 3e000 0000 00 - 3f000 0000 00: heap -3c000 0000 00 - 3ff00 0000 00: - -3ff00 0000 00 - 3ffff f000 00: modules and main thread stack +3f000 0000 00 - 3ffff ffff ff: modules and main thread stack */ -const uptr kLoAppMemBeg = 0x00000400000ull; -const uptr kLoAppMemEnd = 0x01000000000ull; -const uptr kShadowBeg = 0x10000000000ull; -const uptr kShadowEnd = 0x20000000000ull; -const uptr kMetaShadowBeg = 0x26000000000ull; -const uptr kMetaShadowEnd = 0x28000000000ull; -const uptr kTraceMemBeg = 0x36200000000ull; -const uptr kTraceMemEnd = 0x36400000000ull; -const uptr kHeapMemBeg = 0x3e000000000ull; -const uptr kHeapMemEnd = 0x3f000000000ull; -const uptr kHiAppMemBeg = 0x3ff00000000ull; -const uptr kHiAppMemEnd = 0x3fffff00000ull; -const uptr kAppMemMsk = 0x3c000000000ull; -const uptr kAppMemXor = 0x04000000000ull; -const uptr kVdsoBeg = 0x37f00000000ull; -# endif -#endif - -ALWAYS_INLINE -bool IsAppMem(uptr mem) { - return (mem >= kHeapMemBeg && mem < kHeapMemEnd) || - (mem >= kLoAppMemBeg && mem < kLoAppMemEnd) || - (mem >= kHiAppMemBeg && mem < kHiAppMemEnd); -} - -ALWAYS_INLINE -bool IsShadowMem(uptr mem) { - return mem >= kShadowBeg && mem <= kShadowEnd; -} +struct Mapping42 { + static const uptr kLoAppMemBeg = 0x00000001000ull; + static const uptr kLoAppMemEnd = 0x01000000000ull; + static const uptr kShadowBeg = 0x10000000000ull; + static const uptr kShadowEnd = 0x20000000000ull; + static const uptr kMetaShadowBeg = 0x26000000000ull; + static const uptr kMetaShadowEnd = 0x28000000000ull; + static const uptr kMidAppMemBeg = 0x2aa00000000ull; + static const uptr kMidAppMemEnd = 0x2ab00000000ull; + static const uptr kMidShadowOff = 0x28000000000ull; + static const uptr kTraceMemBeg = 0x36200000000ull; + static const uptr kTraceMemEnd = 0x36400000000ull; + static const uptr kHeapMemBeg = 0x3e000000000ull; + static const uptr kHeapMemEnd = 0x3f000000000ull; + static const uptr kHiAppMemBeg = 0x3f000000000ull; + static const uptr kHiAppMemEnd = 0x3ffffffffffull; + static const uptr kAppMemMsk = 0x3c000000000ull; + static const uptr kAppMemXor = 0x04000000000ull; + static const uptr kVdsoBeg = 0x37f00000000ull; +}; -ALWAYS_INLINE -bool IsMetaMem(uptr mem) { - return mem >= kMetaShadowBeg && mem <= kMetaShadowEnd; -} +// Indicates the runtime will define the memory regions at runtime. +#define TSAN_RUNTIME_VMA 1 +// Indicates that mapping defines a mid range memory segment. +#define TSAN_MID_APP_RANGE 1 +#elif defined(__powerpc64__) +// PPC64 supports multiple VMA which leads to multiple address transformation +// functions. To support these multiple VMAS transformations and mappings TSAN +// runtime for PPC64 uses an external memory read (vmaSize) to select which +// mapping to use. Although slower, it make a same instrumented binary run on +// multiple kernels. -ALWAYS_INLINE -uptr MemToShadow(uptr x) { - DCHECK(IsAppMem(x)); - return (((x) & ~(kAppMemMsk | (kShadowCell - 1))) - ^ kAppMemXor) * kShadowCnt; -} - -ALWAYS_INLINE -u32 *MemToMeta(uptr x) { - DCHECK(IsAppMem(x)); - return (u32*)(((((x) & ~(kAppMemMsk | (kMetaShadowCell - 1))) - ^ kAppMemXor) / kMetaShadowCell * kMetaShadowSize) | kMetaShadowBeg); -} - -ALWAYS_INLINE -uptr ShadowToMem(uptr s) { - CHECK(IsShadowMem(s)); - if (s >= MemToShadow(kLoAppMemBeg) && s <= MemToShadow(kLoAppMemEnd - 1)) - return (s / kShadowCnt) ^ kAppMemXor; - else - return ((s / kShadowCnt) ^ kAppMemXor) | kAppMemMsk; -} +/* +C/C++ on linux/powerpc64 (44-bit VMA) +0000 0000 0100 - 0001 0000 0000: main binary +0001 0000 0000 - 0001 0000 0000: - +0001 0000 0000 - 0b00 0000 0000: shadow +0b00 0000 0000 - 0b00 0000 0000: - +0b00 0000 0000 - 0d00 0000 0000: metainfo (memory blocks and sync objects) +0d00 0000 0000 - 0d00 0000 0000: - +0d00 0000 0000 - 0f00 0000 0000: traces +0f00 0000 0000 - 0f00 0000 0000: - +0f00 0000 0000 - 0f50 0000 0000: heap +0f50 0000 0000 - 0f60 0000 0000: - +0f60 0000 0000 - 1000 0000 0000: modules and main thread stack +*/ +struct Mapping44 { + static const uptr kMetaShadowBeg = 0x0b0000000000ull; + static const uptr kMetaShadowEnd = 0x0d0000000000ull; + static const uptr kTraceMemBeg = 0x0d0000000000ull; + static const uptr kTraceMemEnd = 0x0f0000000000ull; + static const uptr kShadowBeg = 0x000100000000ull; + static const uptr kShadowEnd = 0x0b0000000000ull; + static const uptr kLoAppMemBeg = 0x000000000100ull; + static const uptr kLoAppMemEnd = 0x000100000000ull; + static const uptr kHeapMemBeg = 0x0f0000000000ull; + static const uptr kHeapMemEnd = 0x0f5000000000ull; + static const uptr kHiAppMemBeg = 0x0f6000000000ull; + static const uptr kHiAppMemEnd = 0x100000000000ull; // 44 bits + static const uptr kAppMemMsk = 0x0f0000000000ull; + static const uptr kAppMemXor = 0x002100000000ull; + static const uptr kVdsoBeg = 0x3c0000000000000ull; +}; -static USED uptr UserRegions[] = { - kLoAppMemBeg, kLoAppMemEnd, - kHiAppMemBeg, kHiAppMemEnd, - kHeapMemBeg, kHeapMemEnd, +/* +C/C++ on linux/powerpc64 (46-bit VMA) +0000 0000 1000 - 0100 0000 0000: main binary +0100 0000 0000 - 0200 0000 0000: - +0100 0000 0000 - 1000 0000 0000: shadow +1000 0000 0000 - 1000 0000 0000: - +1000 0000 0000 - 2000 0000 0000: metainfo (memory blocks and sync objects) +2000 0000 0000 - 2000 0000 0000: - +2000 0000 0000 - 2200 0000 0000: traces +2200 0000 0000 - 3d00 0000 0000: - +3d00 0000 0000 - 3e00 0000 0000: heap +3e00 0000 0000 - 3e80 0000 0000: - +3e80 0000 0000 - 4000 0000 0000: modules and main thread stack +*/ +struct Mapping46 { + static const uptr kMetaShadowBeg = 0x100000000000ull; + static const uptr kMetaShadowEnd = 0x200000000000ull; + static const uptr kTraceMemBeg = 0x200000000000ull; + static const uptr kTraceMemEnd = 0x220000000000ull; + static const uptr kShadowBeg = 0x010000000000ull; + static const uptr kShadowEnd = 0x100000000000ull; + static const uptr kHeapMemBeg = 0x3d0000000000ull; + static const uptr kHeapMemEnd = 0x3e0000000000ull; + static const uptr kLoAppMemBeg = 0x000000001000ull; + static const uptr kLoAppMemEnd = 0x010000000000ull; + static const uptr kHiAppMemBeg = 0x3e8000000000ull; + static const uptr kHiAppMemEnd = 0x400000000000ull; // 46 bits + static const uptr kAppMemMsk = 0x3c0000000000ull; + static const uptr kAppMemXor = 0x020000000000ull; + static const uptr kVdsoBeg = 0x7800000000000000ull; }; +// Indicates the runtime will define the memory regions at runtime. +#define TSAN_RUNTIME_VMA 1 +#endif + #elif defined(SANITIZER_GO) && !SANITIZER_WINDOWS /* Go on linux, darwin and freebsd @@ -208,138 +263,493 @@ static USED uptr UserRegions[] = { 6200 0000 0000 - 8000 0000 0000: - */ -const uptr kMetaShadowBeg = 0x300000000000ull; -const uptr kMetaShadowEnd = 0x400000000000ull; -const uptr kTraceMemBeg = 0x600000000000ull; -const uptr kTraceMemEnd = 0x620000000000ull; -const uptr kShadowBeg = 0x200000000000ull; -const uptr kShadowEnd = 0x238000000000ull; -const uptr kAppMemBeg = 0x000000001000ull; -const uptr kAppMemEnd = 0x00e000000000ull; +struct Mapping { + static const uptr kMetaShadowBeg = 0x300000000000ull; + static const uptr kMetaShadowEnd = 0x400000000000ull; + static const uptr kTraceMemBeg = 0x600000000000ull; + static const uptr kTraceMemEnd = 0x620000000000ull; + static const uptr kShadowBeg = 0x200000000000ull; + static const uptr kShadowEnd = 0x238000000000ull; + static const uptr kAppMemBeg = 0x000000001000ull; + static const uptr kAppMemEnd = 0x00e000000000ull; +}; + +#elif defined(SANITIZER_GO) && SANITIZER_WINDOWS + +/* Go on windows +0000 0000 1000 - 0000 1000 0000: executable +0000 1000 0000 - 00f8 0000 0000: - +00c0 0000 0000 - 00e0 0000 0000: heap +00e0 0000 0000 - 0100 0000 0000: - +0100 0000 0000 - 0500 0000 0000: shadow +0500 0000 0000 - 0560 0000 0000: - +0560 0000 0000 - 0760 0000 0000: traces +0760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects) +07d0 0000 0000 - 8000 0000 0000: - +*/ + +struct Mapping { + static const uptr kMetaShadowBeg = 0x076000000000ull; + static const uptr kMetaShadowEnd = 0x07d000000000ull; + static const uptr kTraceMemBeg = 0x056000000000ull; + static const uptr kTraceMemEnd = 0x076000000000ull; + static const uptr kShadowBeg = 0x010000000000ull; + static const uptr kShadowEnd = 0x050000000000ull; + static const uptr kAppMemBeg = 0x000000001000ull; + static const uptr kAppMemEnd = 0x00e000000000ull; +} + +#else +# error "Unknown platform" +#endif + + +#ifdef TSAN_RUNTIME_VMA +extern uptr vmaSize; +#endif + + +enum MappingType { + MAPPING_LO_APP_BEG, + MAPPING_LO_APP_END, + MAPPING_HI_APP_BEG, + MAPPING_HI_APP_END, +#ifdef TSAN_MID_APP_RANGE + MAPPING_MID_APP_BEG, + MAPPING_MID_APP_END, +#endif + MAPPING_HEAP_BEG, + MAPPING_HEAP_END, + MAPPING_APP_BEG, + MAPPING_APP_END, + MAPPING_SHADOW_BEG, + MAPPING_SHADOW_END, + MAPPING_META_SHADOW_BEG, + MAPPING_META_SHADOW_END, + MAPPING_TRACE_BEG, + MAPPING_TRACE_END, + MAPPING_VDSO_BEG, +}; + +template +uptr MappingImpl(void) { + switch (Type) { +#ifndef SANITIZER_GO + case MAPPING_LO_APP_BEG: return Mapping::kLoAppMemBeg; + case MAPPING_LO_APP_END: return Mapping::kLoAppMemEnd; +# ifdef TSAN_MID_APP_RANGE + case MAPPING_MID_APP_BEG: return Mapping::kMidAppMemBeg; + case MAPPING_MID_APP_END: return Mapping::kMidAppMemEnd; +# endif + case MAPPING_HI_APP_BEG: return Mapping::kHiAppMemBeg; + case MAPPING_HI_APP_END: return Mapping::kHiAppMemEnd; + case MAPPING_HEAP_BEG: return Mapping::kHeapMemBeg; + case MAPPING_HEAP_END: return Mapping::kHeapMemEnd; + case MAPPING_VDSO_BEG: return Mapping::kVdsoBeg; +#else + case MAPPING_APP_BEG: return Mapping::kAppMemBeg; + case MAPPING_APP_END: return Mapping::kAppMemEnd; +#endif + case MAPPING_SHADOW_BEG: return Mapping::kShadowBeg; + case MAPPING_SHADOW_END: return Mapping::kShadowEnd; + case MAPPING_META_SHADOW_BEG: return Mapping::kMetaShadowBeg; + case MAPPING_META_SHADOW_END: return Mapping::kMetaShadowEnd; + case MAPPING_TRACE_BEG: return Mapping::kTraceMemBeg; + case MAPPING_TRACE_END: return Mapping::kTraceMemEnd; + } +} + +template +uptr MappingArchImpl(void) { +#ifdef __aarch64__ + if (vmaSize == 39) + return MappingImpl(); + else + return MappingImpl(); + DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return MappingImpl(); + else + return MappingImpl(); + DCHECK(0); +#else + return MappingImpl(); +#endif +} +#ifndef SANITIZER_GO ALWAYS_INLINE -bool IsAppMem(uptr mem) { - return mem >= kAppMemBeg && mem < kAppMemEnd; +uptr LoAppMemBeg(void) { + return MappingArchImpl(); +} +ALWAYS_INLINE +uptr LoAppMemEnd(void) { + return MappingArchImpl(); } +#ifdef TSAN_MID_APP_RANGE ALWAYS_INLINE -bool IsShadowMem(uptr mem) { - return mem >= kShadowBeg && mem <= kShadowEnd; +uptr MidAppMemBeg(void) { + return MappingArchImpl(); } +ALWAYS_INLINE +uptr MidAppMemEnd(void) { + return MappingArchImpl(); +} +#endif ALWAYS_INLINE -bool IsMetaMem(uptr mem) { - return mem >= kMetaShadowBeg && mem <= kMetaShadowEnd; +uptr HeapMemBeg(void) { + return MappingArchImpl(); +} +ALWAYS_INLINE +uptr HeapMemEnd(void) { + return MappingArchImpl(); } ALWAYS_INLINE -uptr MemToShadow(uptr x) { - DCHECK(IsAppMem(x)); - return ((x & ~(kShadowCell - 1)) * kShadowCnt) | kShadowBeg; +uptr HiAppMemBeg(void) { + return MappingArchImpl(); +} +ALWAYS_INLINE +uptr HiAppMemEnd(void) { + return MappingArchImpl(); } ALWAYS_INLINE -u32 *MemToMeta(uptr x) { - DCHECK(IsAppMem(x)); - return (u32*)(((x & ~(kMetaShadowCell - 1)) / \ - kMetaShadowCell * kMetaShadowSize) | kMetaShadowBeg); +uptr VdsoBeg(void) { + return MappingArchImpl(); } +#else + ALWAYS_INLINE -uptr ShadowToMem(uptr s) { - CHECK(IsShadowMem(s)); - return (s & ~kShadowBeg) / kShadowCnt; +uptr AppMemBeg(void) { + return MappingArchImpl(); +} +ALWAYS_INLINE +uptr AppMemEnd(void) { + return MappingArchImpl(); } -static USED uptr UserRegions[] = { - kAppMemBeg, kAppMemEnd, -}; +#endif -#elif defined(SANITIZER_GO) && SANITIZER_WINDOWS +static inline +bool GetUserRegion(int i, uptr *start, uptr *end) { + switch (i) { + default: + return false; +#ifndef SANITIZER_GO + case 0: + *start = LoAppMemBeg(); + *end = LoAppMemEnd(); + return true; + case 1: + *start = HiAppMemBeg(); + *end = HiAppMemEnd(); + return true; + case 2: + *start = HeapMemBeg(); + *end = HeapMemEnd(); + return true; +# ifdef TSAN_MID_APP_RANGE + case 3: + *start = MidAppMemBeg(); + *end = MidAppMemEnd(); + return true; +# endif +#else + case 0: + *start = AppMemBeg(); + *end = AppMemEnd(); + return true; +#endif + } +} -/* Go on windows -0000 0000 1000 - 0000 1000 0000: executable -0000 1000 0000 - 00f8 0000 0000: - -00c0 0000 0000 - 00e0 0000 0000: heap -00e0 0000 0000 - 0100 0000 0000: - -0100 0000 0000 - 0500 0000 0000: shadow -0500 0000 0000 - 0560 0000 0000: - -0560 0000 0000 - 0760 0000 0000: traces -0760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects) -07d0 0000 0000 - 8000 0000 0000: - -*/ +ALWAYS_INLINE +uptr ShadowBeg(void) { + return MappingArchImpl(); +} +ALWAYS_INLINE +uptr ShadowEnd(void) { + return MappingArchImpl(); +} -const uptr kMetaShadowBeg = 0x076000000000ull; -const uptr kMetaShadowEnd = 0x07d000000000ull; -const uptr kTraceMemBeg = 0x056000000000ull; -const uptr kTraceMemEnd = 0x076000000000ull; -const uptr kShadowBeg = 0x010000000000ull; -const uptr kShadowEnd = 0x050000000000ull; -const uptr kAppMemBeg = 0x000000001000ull; -const uptr kAppMemEnd = 0x00e000000000ull; +ALWAYS_INLINE +uptr MetaShadowBeg(void) { + return MappingArchImpl(); +} +ALWAYS_INLINE +uptr MetaShadowEnd(void) { + return MappingArchImpl(); +} + +ALWAYS_INLINE +uptr TraceMemBeg(void) { + return MappingArchImpl(); +} +ALWAYS_INLINE +uptr TraceMemEnd(void) { + return MappingArchImpl(); +} + + +template +bool IsAppMemImpl(uptr mem) { +#ifndef SANITIZER_GO + return (mem >= Mapping::kHeapMemBeg && mem < Mapping::kHeapMemEnd) || +# ifdef TSAN_MID_APP_RANGE + (mem >= Mapping::kMidAppMemBeg && mem < Mapping::kMidAppMemEnd) || +# endif + (mem >= Mapping::kLoAppMemBeg && mem < Mapping::kLoAppMemEnd) || + (mem >= Mapping::kHiAppMemBeg && mem < Mapping::kHiAppMemEnd); +#else + return mem >= Mapping::kAppMemBeg && mem < Mapping::kAppMemEnd; +#endif +} ALWAYS_INLINE bool IsAppMem(uptr mem) { - return mem >= kAppMemBeg && mem < kAppMemEnd; +#ifdef __aarch64__ + if (vmaSize == 39) + return IsAppMemImpl(mem); + else + return IsAppMemImpl(mem); + DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return IsAppMemImpl(mem); + else + return IsAppMemImpl(mem); + DCHECK(0); +#else + return IsAppMemImpl(mem); +#endif +} + + +template +bool IsShadowMemImpl(uptr mem) { + return mem >= Mapping::kShadowBeg && mem <= Mapping::kShadowEnd; } ALWAYS_INLINE bool IsShadowMem(uptr mem) { - return mem >= kShadowBeg && mem <= kShadowEnd; +#ifdef __aarch64__ + if (vmaSize == 39) + return IsShadowMemImpl(mem); + else + return IsShadowMemImpl(mem); + DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return IsShadowMemImpl(mem); + else + return IsShadowMemImpl(mem); + DCHECK(0); +#else + return IsShadowMemImpl(mem); +#endif +} + + +template +bool IsMetaMemImpl(uptr mem) { + return mem >= Mapping::kMetaShadowBeg && mem <= Mapping::kMetaShadowEnd; } ALWAYS_INLINE bool IsMetaMem(uptr mem) { - return mem >= kMetaShadowBeg && mem <= kMetaShadowEnd; +#ifdef __aarch64__ + if (vmaSize == 39) + return IsMetaMemImpl(mem); + else + return IsMetaMemImpl(mem); + DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return IsMetaMemImpl(mem); + else + return IsMetaMemImpl(mem); + DCHECK(0); +#else + return IsMetaMemImpl(mem); +#endif } -ALWAYS_INLINE -uptr MemToShadow(uptr x) { + +template +uptr MemToShadowImpl(uptr x) { DCHECK(IsAppMem(x)); - return ((x & ~(kShadowCell - 1)) * kShadowCnt) + kShadowBeg; +#ifndef SANITIZER_GO + return (((x) & ~(Mapping::kAppMemMsk | (kShadowCell - 1))) + ^ Mapping::kAppMemXor) * kShadowCnt; +#else + return ((x & ~(kShadowCell - 1)) * kShadowCnt) | Mapping::kShadowBeg; +#endif } ALWAYS_INLINE -u32 *MemToMeta(uptr x) { +uptr MemToShadow(uptr x) { +#ifdef __aarch64__ + if (vmaSize == 39) + return MemToShadowImpl(x); + else + return MemToShadowImpl(x); + DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return MemToShadowImpl(x); + else + return MemToShadowImpl(x); + DCHECK(0); +#else + return MemToShadowImpl(x); +#endif +} + + +template +u32 *MemToMetaImpl(uptr x) { DCHECK(IsAppMem(x)); +#ifndef SANITIZER_GO + return (u32*)(((((x) & ~(Mapping::kAppMemMsk | (kMetaShadowCell - 1))) + ^ Mapping::kAppMemXor) / kMetaShadowCell * kMetaShadowSize) + | Mapping::kMetaShadowBeg); +#else return (u32*)(((x & ~(kMetaShadowCell - 1)) / \ - kMetaShadowCell * kMetaShadowSize) | kMetaShadowBeg); + kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg); +#endif } ALWAYS_INLINE -uptr ShadowToMem(uptr s) { - CHECK(IsShadowMem(s)); - // FIXME(dvyukov): this is most likely wrong as the mapping is not bijection. - return (s - kShadowBeg) / kShadowCnt; +u32 *MemToMeta(uptr x) { +#ifdef __aarch64__ + if (vmaSize == 39) + return MemToMetaImpl(x); + else + return MemToMetaImpl(x); + DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return MemToMetaImpl(x); + else + return MemToMetaImpl(x); + DCHECK(0); +#else + return MemToMetaImpl(x); +#endif } -static USED uptr UserRegions[] = { - kAppMemBeg, kAppMemEnd, -}; +template +uptr ShadowToMemImpl(uptr s) { + DCHECK(IsShadowMem(s)); +#ifndef SANITIZER_GO + if (s >= MemToShadow(Mapping::kLoAppMemBeg) + && s <= MemToShadow(Mapping::kLoAppMemEnd - 1)) + return (s / kShadowCnt) ^ Mapping::kAppMemXor; +# ifdef TSAN_MID_APP_RANGE + if (s >= MemToShadow(Mapping::kMidAppMemBeg) + && s <= MemToShadow(Mapping::kMidAppMemEnd - 1)) + return ((s / kShadowCnt) ^ Mapping::kAppMemXor) + Mapping::kMidShadowOff; +# endif + else + return ((s / kShadowCnt) ^ Mapping::kAppMemXor) | Mapping::kAppMemMsk; #else -# error "Unknown platform" +# ifndef SANITIZER_WINDOWS + return (s & ~Mapping::kShadowBeg) / kShadowCnt; +# else + // FIXME(dvyukov): this is most likely wrong as the mapping is not bijection. + return (s - Mapping::kShadowBeg) / kShadowCnt; +# endif // SANITIZER_WINDOWS #endif +} + +ALWAYS_INLINE +uptr ShadowToMem(uptr s) { +#ifdef __aarch64__ + if (vmaSize == 39) + return ShadowToMemImpl(s); + else + return ShadowToMemImpl(s); + DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return ShadowToMemImpl(s); + else + return ShadowToMemImpl(s); + DCHECK(0); +#else + return ShadowToMemImpl(s); +#endif +} + + // The additional page is to catch shadow stack overflow as paging fault. // Windows wants 64K alignment for mmaps. const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace) + (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1); -uptr ALWAYS_INLINE GetThreadTrace(int tid) { - uptr p = kTraceMemBeg + (uptr)tid * kTotalTraceSize; - DCHECK_LT(p, kTraceMemEnd); +template +uptr GetThreadTraceImpl(int tid) { + uptr p = Mapping::kTraceMemBeg + (uptr)tid * kTotalTraceSize; + DCHECK_LT(p, Mapping::kTraceMemEnd); return p; } -uptr ALWAYS_INLINE GetThreadTraceHeader(int tid) { - uptr p = kTraceMemBeg + (uptr)tid * kTotalTraceSize +ALWAYS_INLINE +uptr GetThreadTrace(int tid) { +#ifdef __aarch64__ + if (vmaSize == 39) + return GetThreadTraceImpl(tid); + else + return GetThreadTraceImpl(tid); + DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return GetThreadTraceImpl(tid); + else + return GetThreadTraceImpl(tid); + DCHECK(0); +#else + return GetThreadTraceImpl(tid); +#endif +} + + +template +uptr GetThreadTraceHeaderImpl(int tid) { + uptr p = Mapping::kTraceMemBeg + (uptr)tid * kTotalTraceSize + kTraceSize * sizeof(Event); - DCHECK_LT(p, kTraceMemEnd); + DCHECK_LT(p, Mapping::kTraceMemEnd); return p; } +ALWAYS_INLINE +uptr GetThreadTraceHeader(int tid) { +#ifdef __aarch64__ + if (vmaSize == 39) + return GetThreadTraceHeaderImpl(tid); + else + return GetThreadTraceHeaderImpl(tid); + DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return GetThreadTraceHeaderImpl(tid); + else + return GetThreadTraceHeaderImpl(tid); + DCHECK(0); +#else + return GetThreadTraceHeaderImpl(tid); +#endif +} + void InitializePlatform(); +void InitializePlatformEarly(); void CheckAndProtect(); void InitializeShadowMemoryPlatform(); void FlushShadowMemory(); diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/src/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc index f6c704051c..6602561186 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc @@ -67,6 +67,11 @@ namespace __tsan { static uptr g_data_start; static uptr g_data_end; +#ifdef TSAN_RUNTIME_VMA +// Runtime detected VMA size. +uptr vmaSize; +#endif + enum { MemTotal = 0, MemShadow = 1, @@ -82,29 +87,30 @@ enum { void FillProfileCallback(uptr p, uptr rss, bool file, uptr *mem, uptr stats_size) { mem[MemTotal] += rss; - if (p >= kShadowBeg && p < kShadowEnd) + if (p >= ShadowBeg() && p < ShadowEnd()) mem[MemShadow] += rss; - else if (p >= kMetaShadowBeg && p < kMetaShadowEnd) + else if (p >= MetaShadowBeg() && p < MetaShadowEnd()) mem[MemMeta] += rss; #ifndef SANITIZER_GO - else if (p >= kHeapMemBeg && p < kHeapMemEnd) + else if (p >= HeapMemBeg() && p < HeapMemEnd()) mem[MemHeap] += rss; - else if (p >= kLoAppMemBeg && p < kLoAppMemEnd) + else if (p >= LoAppMemBeg() && p < LoAppMemEnd()) mem[file ? MemFile : MemMmap] += rss; - else if (p >= kHiAppMemBeg && p < kHiAppMemEnd) + else if (p >= HiAppMemBeg() && p < HiAppMemEnd()) mem[file ? MemFile : MemMmap] += rss; #else - else if (p >= kAppMemBeg && p < kAppMemEnd) + else if (p >= AppMemBeg() && p < AppMemEnd()) mem[file ? MemFile : MemMmap] += rss; #endif - else if (p >= kTraceMemBeg && p < kTraceMemEnd) + else if (p >= TraceMemBeg() && p < TraceMemEnd()) mem[MemTrace] += rss; else mem[MemOther] += rss; } void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) { - uptr mem[MemCount] = {}; + uptr mem[MemCount]; + internal_memset(mem, 0, sizeof(mem[0]) * MemCount); __sanitizer::GetMemoryProfile(FillProfileCallback, mem, 7); StackDepotStats *stacks = StackDepotGetStats(); internal_snprintf(buf, buf_size, @@ -121,7 +127,7 @@ void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) { void FlushShadowMemoryCallback( const SuspendedThreadsList &suspended_threads_list, void *argument) { - FlushUnneededShadowMemory(kShadowBeg, kShadowEnd - kShadowBeg); + FlushUnneededShadowMemory(ShadowBeg(), ShadowEnd() - ShadowBeg()); } #endif @@ -235,6 +241,26 @@ static void InitDataSeg() { #endif // #ifndef SANITIZER_GO +void InitializePlatformEarly() { +#ifdef TSAN_RUNTIME_VMA + vmaSize = + (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); +#if defined(__aarch64__) + if (vmaSize != 39 && vmaSize != 42) { + Printf("FATAL: ThreadSanitizer: unsupported VMA range\n"); + Printf("FATAL: Found %d - Supported 39 and 42\n", vmaSize); + Die(); + } +#elif defined(__powerpc64__) + if (vmaSize != 44 && vmaSize != 46) { + Printf("FATAL: ThreadSanitizer: unsupported VMA range\n"); + Printf("FATAL: Found %d - Supported 44 and 46\n", vmaSize); + Die(); + } +#endif +#endif +} + void InitializePlatform() { DisableCoreDumperIfNecessary(); @@ -283,7 +309,7 @@ bool IsGlobalVar(uptr addr) { // This is required to properly "close" the fds, because we do not see internal // closes within glibc. The code is a pure hack. int ExtractResolvFDs(void *state, int *fds, int nfd) { -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !SANITIZER_ANDROID int cnt = 0; __res_state *statp = (__res_state*)state; for (int i = 0; i < MAXNS && cnt < nfd; i++) { diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc b/src/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc index 446d790019..31caf37dee 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc @@ -42,6 +42,7 @@ namespace __tsan { +#ifndef SANITIZER_GO static void *SignalSafeGetOrAllocate(uptr *dst, uptr size) { atomic_uintptr_t *a = (atomic_uintptr_t *)dst; void *val = (void *)atomic_load_relaxed(a); @@ -61,7 +62,6 @@ static void *SignalSafeGetOrAllocate(uptr *dst, uptr size) { return val; } -#ifndef SANITIZER_GO // On OS X, accessing TLVs via __thread or manually by using pthread_key_* is // problematic, because there are several places where interceptors are called // when TLVs are not accessible (early process startup, thread cleanup, ...). @@ -110,7 +110,6 @@ void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) { #ifndef SANITIZER_GO void InitializeShadowMemoryPlatform() { } -#endif // On OS X, GCD worker threads are created without a call to pthread_create. We // need to properly register these threads with ThreadCreate and ThreadStart. @@ -125,7 +124,7 @@ typedef void (*pthread_introspection_hook_t)(unsigned int event, extern "C" pthread_introspection_hook_t pthread_introspection_hook_install( pthread_introspection_hook_t hook); static const uptr PTHREAD_INTROSPECTION_THREAD_CREATE = 1; -static const uptr PTHREAD_INTROSPECTION_THREAD_DESTROY = 4; +static const uptr PTHREAD_INTROSPECTION_THREAD_TERMINATE = 3; static pthread_introspection_hook_t prev_pthread_introspection_hook; static void my_pthread_introspection_hook(unsigned int event, pthread_t thread, void *addr, size_t size) { @@ -138,16 +137,22 @@ static void my_pthread_introspection_hook(unsigned int event, pthread_t thread, ThreadState *thr = cur_thread(); ThreadStart(thr, tid, GetTid()); } - } else if (event == PTHREAD_INTROSPECTION_THREAD_DESTROY) { - ThreadState *thr = cur_thread(); - if (thr->tctx->parent_tid == kInvalidTid) { - DestroyThreadState(); + } else if (event == PTHREAD_INTROSPECTION_THREAD_TERMINATE) { + if (thread == pthread_self()) { + ThreadState *thr = cur_thread(); + if (thr->tctx) { + DestroyThreadState(); + } } } if (prev_pthread_introspection_hook != nullptr) prev_pthread_introspection_hook(event, thread, addr, size); } +#endif + +void InitializePlatformEarly() { +} void InitializePlatform() { DisableCoreDumperIfNecessary(); @@ -156,10 +161,10 @@ void InitializePlatform() { CHECK_EQ(main_thread_identity, 0); main_thread_identity = (uptr)pthread_self(); -#endif prev_pthread_introspection_hook = pthread_introspection_hook_install(&my_pthread_introspection_hook); +#endif } #ifndef SANITIZER_GO diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc b/src/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc index 1782bf1407..90476cbc5f 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc @@ -27,11 +27,12 @@ namespace __tsan { void InitializeShadowMemory() { // Map memory shadow. uptr shadow = - (uptr)MmapFixedNoReserve(kShadowBeg, kShadowEnd - kShadowBeg, "shadow"); - if (shadow != kShadowBeg) { + (uptr)MmapFixedNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(), + "shadow"); + if (shadow != ShadowBeg()) { Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); Printf("FATAL: Make sure to compile with -fPIE and " - "to link with -pie (%p, %p).\n", shadow, kShadowBeg); + "to link with -pie (%p, %p).\n", shadow, ShadowBeg()); Die(); } // This memory range is used for thread stacks and large user mmaps. @@ -46,29 +47,50 @@ void InitializeShadowMemory() { const uptr kMadviseRangeBeg = 0xff00000000ull; const uptr kMadviseRangeSize = 0x0100000000ull; #elif defined(__aarch64__) - const uptr kMadviseRangeBeg = 0x7e00000000ull; - const uptr kMadviseRangeSize = 0x0100000000ull; + uptr kMadviseRangeBeg = 0; + uptr kMadviseRangeSize = 0; + if (vmaSize == 39) { + kMadviseRangeBeg = 0x7d00000000ull; + kMadviseRangeSize = 0x0300000000ull; + } else if (vmaSize == 42) { + kMadviseRangeBeg = 0x3f000000000ull; + kMadviseRangeSize = 0x01000000000ull; + } else { + DCHECK(0); + } +#elif defined(__powerpc64__) + uptr kMadviseRangeBeg = 0; + uptr kMadviseRangeSize = 0; + if (vmaSize == 44) { + kMadviseRangeBeg = 0x0f60000000ull; + kMadviseRangeSize = 0x0010000000ull; + } else if (vmaSize == 46) { + kMadviseRangeBeg = 0x3f0000000000ull; + kMadviseRangeSize = 0x010000000000ull; + } else { + DCHECK(0); + } #endif NoHugePagesInRegion(MemToShadow(kMadviseRangeBeg), kMadviseRangeSize * kShadowMultiplier); // Meta shadow is compressing and we don't flush it, // so it makes sense to mark it as NOHUGEPAGE to not over-allocate memory. // On one program it reduces memory consumption from 5GB to 2.5GB. - NoHugePagesInRegion(kMetaShadowBeg, kMetaShadowEnd - kMetaShadowBeg); + NoHugePagesInRegion(MetaShadowBeg(), MetaShadowEnd() - MetaShadowBeg()); if (common_flags()->use_madv_dontdump) - DontDumpShadowMemory(kShadowBeg, kShadowEnd - kShadowBeg); + DontDumpShadowMemory(ShadowBeg(), ShadowEnd() - ShadowBeg()); DPrintf("memory shadow: %zx-%zx (%zuGB)\n", - kShadowBeg, kShadowEnd, - (kShadowEnd - kShadowBeg) >> 30); + ShadowBeg(), ShadowEnd(), + (ShadowEnd() - ShadowBeg()) >> 30); // Map meta shadow. - uptr meta_size = kMetaShadowEnd - kMetaShadowBeg; + uptr meta_size = MetaShadowEnd() - MetaShadowBeg(); uptr meta = - (uptr)MmapFixedNoReserve(kMetaShadowBeg, meta_size, "meta shadow"); - if (meta != kMetaShadowBeg) { + (uptr)MmapFixedNoReserve(MetaShadowBeg(), meta_size, "meta shadow"); + if (meta != MetaShadowBeg()) { Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); Printf("FATAL: Make sure to compile with -fPIE and " - "to link with -pie (%p, %p).\n", meta, kMetaShadowBeg); + "to link with -pie (%p, %p).\n", meta, MetaShadowBeg()); Die(); } if (common_flags()->use_madv_dontdump) @@ -97,25 +119,30 @@ void CheckAndProtect() { while (proc_maps.Next(&p, &end, 0, 0, 0, &prot)) { if (IsAppMem(p)) continue; - if (p >= kHeapMemEnd && + if (p >= HeapMemEnd() && p < HeapEnd()) continue; if (prot == 0) // Zero page or mprotected. continue; - if (p >= kVdsoBeg) // vdso + if (p >= VdsoBeg()) // vdso break; Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n", p, end); Die(); } - ProtectRange(kLoAppMemEnd, kShadowBeg); - ProtectRange(kShadowEnd, kMetaShadowBeg); - ProtectRange(kMetaShadowEnd, kTraceMemBeg); + ProtectRange(LoAppMemEnd(), ShadowBeg()); + ProtectRange(ShadowEnd(), MetaShadowBeg()); +#ifdef TSAN_MID_APP_RANGE + ProtectRange(MetaShadowEnd(), MidAppMemBeg()); + ProtectRange(MidAppMemEnd(), TraceMemBeg()); +#else + ProtectRange(MetaShadowEnd(), TraceMemBeg()); +#endif // Memory for traces is mapped lazily in MapThreadTrace. // Protect the whole range for now, so that user does not map something here. - ProtectRange(kTraceMemBeg, kTraceMemEnd); - ProtectRange(kTraceMemEnd, kHeapMemBeg); - ProtectRange(HeapEnd(), kHiAppMemBeg); + ProtectRange(TraceMemBeg(), TraceMemEnd()); + ProtectRange(TraceMemEnd(), HeapMemBeg()); + ProtectRange(HeapEnd(), HiAppMemBeg()); } #endif diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_platform_windows.cc b/src/compiler-rt/lib/tsan/rtl/tsan_platform_windows.cc index cfbe77da2c..c6d5058d96 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_platform_windows.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_platform_windows.cc @@ -31,6 +31,9 @@ void FlushShadowMemory() { void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) { } +void InitializePlatformEarly() { +} + void InitializePlatform() { } diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_ppc_regs.h b/src/compiler-rt/lib/tsan/rtl/tsan_ppc_regs.h new file mode 100644 index 0000000000..5b43f3ddad --- /dev/null +++ b/src/compiler-rt/lib/tsan/rtl/tsan_ppc_regs.h @@ -0,0 +1,96 @@ +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r11 11 +#define r12 12 +#define r13 13 +#define r14 14 +#define r15 15 +#define r16 16 +#define r17 17 +#define r18 18 +#define r19 19 +#define r20 20 +#define r21 21 +#define r22 22 +#define r23 23 +#define r24 24 +#define r25 25 +#define r26 26 +#define r27 27 +#define r28 28 +#define r29 29 +#define r30 30 +#define r31 31 +#define f0 0 +#define f1 1 +#define f2 2 +#define f3 3 +#define f4 4 +#define f5 5 +#define f6 6 +#define f7 7 +#define f8 8 +#define f9 9 +#define f10 10 +#define f11 11 +#define f12 12 +#define f13 13 +#define f14 14 +#define f15 15 +#define f16 16 +#define f17 17 +#define f18 18 +#define f19 19 +#define f20 20 +#define f21 21 +#define f22 22 +#define f23 23 +#define f24 24 +#define f25 25 +#define f26 26 +#define f27 27 +#define f28 28 +#define f29 29 +#define f30 30 +#define f31 31 +#define v0 0 +#define v1 1 +#define v2 2 +#define v3 3 +#define v4 4 +#define v5 5 +#define v6 6 +#define v7 7 +#define v8 8 +#define v9 9 +#define v10 10 +#define v11 11 +#define v12 12 +#define v13 13 +#define v14 14 +#define v15 15 +#define v16 16 +#define v17 17 +#define v18 18 +#define v19 19 +#define v20 20 +#define v21 21 +#define v22 22 +#define v23 23 +#define v24 24 +#define v25 25 +#define v26 26 +#define v27 27 +#define v28 28 +#define v29 29 +#define v30 30 +#define v31 31 diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_report.cc b/src/compiler-rt/lib/tsan/rtl/tsan_report.cc index f4b06878a5..c1d2fd07c0 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_report.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_report.cc @@ -111,6 +111,12 @@ static const char *ReportTypeString(ReportType typ) { return ""; } +#if SANITIZER_MAC +static const char *const kInterposedFunctionPrefix = "wrap_"; +#else +static const char *const kInterposedFunctionPrefix = "__interceptor_"; +#endif + void PrintStack(const ReportStack *ent) { if (ent == 0 || ent->frames == 0) { Printf(" [failed to restore the stack]\n\n"); @@ -121,7 +127,7 @@ void PrintStack(const ReportStack *ent) { InternalScopedString res(2 * GetPageSizeCached()); RenderFrame(&res, common_flags()->stack_trace_format, i, frame->info, common_flags()->symbolize_vs_style, - common_flags()->strip_path_prefix, "__interceptor_"); + common_flags()->strip_path_prefix, kInterposedFunctionPrefix); Printf("%s\n", res.data()); } Printf("\n"); @@ -165,9 +171,14 @@ static void PrintLocation(const ReportLocation *loc) { Printf("%s", d.Location()); if (loc->type == ReportLocationGlobal) { const DataInfo &global = loc->global; - Printf(" Location is global '%s' of size %zu at %p (%s+%p)\n\n", - global.name, global.size, global.start, - StripModuleName(global.module), global.module_offset); + if (global.size != 0) + Printf(" Location is global '%s' of size %zu at %p (%s+%p)\n\n", + global.name, global.size, global.start, + StripModuleName(global.module), global.module_offset); + else + Printf(" Location is global '%s' at %p (%s+%p)\n\n", global.name, + global.start, StripModuleName(global.module), + global.module_offset); } else if (loc->type == ReportLocationHeap) { char thrbuf[kThreadBufSize]; Printf(" Location is heap block of size %zu at %p allocated by %s:\n", @@ -256,10 +267,15 @@ static bool FrameIsInternal(const SymbolizedStack *frame) { if (frame == 0) return false; const char *file = frame->info.file; - return file != 0 && - (internal_strstr(file, "tsan_interceptors.cc") || - internal_strstr(file, "sanitizer_common_interceptors.inc") || - internal_strstr(file, "tsan_interface_")); + const char *module = frame->info.module; + if (file != 0 && + (internal_strstr(file, "tsan_interceptors.cc") || + internal_strstr(file, "sanitizer_common_interceptors.inc") || + internal_strstr(file, "tsan_interface_"))) + return true; + if (module != 0 && (internal_strstr(module, "libclang_rt.tsan_"))) + return true; + return false; } static SymbolizedStack *SkipTsanInternalFrames(SymbolizedStack *frames) { diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/src/compiler-rt/lib/tsan/rtl/tsan_rtl.cc index 05d530e982..4df4db557a 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_rtl.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_rtl.cc @@ -55,12 +55,12 @@ Context *ctx; bool OnFinalize(bool failed); void OnInitialize(); #else -SANITIZER_INTERFACE_ATTRIBUTE -bool WEAK OnFinalize(bool failed) { +SANITIZER_WEAK_CXX_DEFAULT_IMPL +bool OnFinalize(bool failed) { return failed; } -SANITIZER_INTERFACE_ATTRIBUTE -void WEAK OnInitialize() {} +SANITIZER_WEAK_CXX_DEFAULT_IMPL +void OnInitialize() {} #endif static char thread_registry_placeholder[sizeof(ThreadRegistry)]; @@ -273,8 +273,8 @@ void MapShadow(uptr addr, uptr size) { void MapThreadTrace(uptr addr, uptr size, const char *name) { DPrintf("#0: Mapping trace at %p-%p(0x%zx)\n", addr, addr + size, size); - CHECK_GE(addr, kTraceMemBeg); - CHECK_LE(addr + size, kTraceMemEnd); + CHECK_GE(addr, TraceMemBeg()); + CHECK_LE(addr + size, TraceMemEnd()); CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment uptr addr1 = (uptr)MmapFixedNoReserve(addr, size, name); if (addr1 != addr) { @@ -285,9 +285,8 @@ void MapThreadTrace(uptr addr, uptr size, const char *name) { } static void CheckShadowMapping() { - for (uptr i = 0; i < ARRAY_SIZE(UserRegions); i += 2) { - const uptr beg = UserRegions[i]; - const uptr end = UserRegions[i + 1]; + uptr beg, end; + for (int i = 0; GetUserRegion(i, &beg, &end); i++) { VPrintf(3, "checking shadow region %p-%p\n", beg, end); for (uptr p0 = beg; p0 <= end; p0 += (end - beg) / 4) { for (int x = -1; x <= 1; x++) { @@ -322,8 +321,11 @@ void Initialize(ThreadState *thr) { const char *options = GetEnv(kTsanOptionsEnv); CacheBinaryName(); InitializeFlags(&ctx->flags, options); - CheckVMASize(); + InitializePlatformEarly(); #ifndef SANITIZER_GO + // Re-exec ourselves if we need to set additional env or command line args. + MaybeReexec(); + InitializeAllocator(); ReplaceSystemMalloc(); #endif diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/src/compiler-rt/lib/tsan/rtl/tsan_rtl.h index 2e6be3ff06..04104b162f 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/src/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -54,7 +54,7 @@ namespace __tsan { #ifndef SANITIZER_GO struct MapUnmapCallback; -#if defined(__mips64) || defined(__aarch64__) +#if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__) static const uptr kAllocatorSpace = 0; static const uptr kAllocatorSize = SANITIZER_MMAP_RANGE_SIZE; static const uptr kAllocatorRegionSizeLog = 20; @@ -66,7 +66,8 @@ typedef SizeClassAllocator32 PrimaryAllocator; #else -typedef SizeClassAllocator64 PrimaryAllocator; #endif typedef SizeClassAllocatorLocalCache AllocatorCache; @@ -761,7 +762,7 @@ void ALWAYS_INLINE TraceAddEvent(ThreadState *thr, FastState fs, #ifndef SANITIZER_GO uptr ALWAYS_INLINE HeapEnd() { - return kHeapMemEnd + PrimaryAllocator::AdditionalSize(); + return HeapMemEnd() + PrimaryAllocator::AdditionalSize(); } #endif diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S b/src/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S new file mode 100644 index 0000000000..9cea3cf028 --- /dev/null +++ b/src/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S @@ -0,0 +1,206 @@ +#include "sanitizer_common/sanitizer_asm.h" +.section .text + +.hidden __tsan_setjmp +.comm _ZN14__interception11real_setjmpE,8,8 +.type setjmp, @function +setjmp: + CFI_STARTPROC + + // save env parameters for function call + stp x29, x30, [sp, -32]! + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (29, -32) + CFI_OFFSET (30, -24) + + // Adjust the SP for previous frame + add x29, sp, 0 + CFI_DEF_CFA_REGISTER (29) + + // Save jmp_buf + str x19, [sp, 16] + CFI_OFFSET (19, -16) + mov x19, x0 + + // SP pointer mangling (see glibc setjmp) + adrp x2, :got:__pointer_chk_guard + ldr x2, [x2, #:got_lo12:__pointer_chk_guard] + add x0, x29, 32 + ldr x2, [x2] + eor x1, x2, x0 + + // call tsan interceptor + bl __tsan_setjmp + + // restore env parameter + mov x0, x19 + ldr x19, [sp, 16] + ldp x29, x30, [sp], 32 + CFI_RESTORE (30) + CFI_RESTORE (19) + CFI_DEF_CFA (31, 0) + + // tail jump to libc setjmp + adrp x1, :got:_ZN14__interception11real_setjmpE + ldr x1, [x1, #:got_lo12:_ZN14__interception11real_setjmpE] + ldr x1, [x1] + br x1 + + CFI_ENDPROC +.size setjmp, .-setjmp + +.comm _ZN14__interception12real__setjmpE,8,8 +.globl _setjmp +.type _setjmp, @function +_setjmp: + CFI_STARTPROC + + // save env parameters for function call + stp x29, x30, [sp, -32]! + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (29, -32) + CFI_OFFSET (30, -24) + + // Adjust the SP for previous frame + add x29, sp, 0 + CFI_DEF_CFA_REGISTER (29) + + // Save jmp_buf + str x19, [sp, 16] + CFI_OFFSET (19, -16) + mov x19, x0 + + // SP pointer mangling (see glibc setjmp) + adrp x2, :got:__pointer_chk_guard + ldr x2, [x2, #:got_lo12:__pointer_chk_guard] + add x0, x29, 32 + ldr x2, [x2] + eor x1, x2, x0 + + // call tsan interceptor + bl __tsan_setjmp + + // Restore jmp_buf parameter + mov x0, x19 + ldr x19, [sp, 16] + ldp x29, x30, [sp], 32 + CFI_RESTORE (30) + CFI_RESTORE (19) + CFI_DEF_CFA (31, 0) + + // tail jump to libc setjmp + adrp x1, :got:_ZN14__interception12real__setjmpE + ldr x1, [x1, #:got_lo12:_ZN14__interception12real__setjmpE] + ldr x1, [x1] + br x1 + + CFI_ENDPROC +.size _setjmp, .-_setjmp + +.comm _ZN14__interception14real_sigsetjmpE,8,8 +.globl sigsetjmp +.type sigsetjmp, @function +sigsetjmp: + CFI_STARTPROC + + // save env parameters for function call + stp x29, x30, [sp, -32]! + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (29, -32) + CFI_OFFSET (30, -24) + + // Adjust the SP for previous frame + add x29, sp, 0 + CFI_DEF_CFA_REGISTER (29) + + // Save jmp_buf and savesigs + stp x19, x20, [sp, 16] + CFI_OFFSET (19, -16) + CFI_OFFSET (20, -8) + mov w20, w1 + mov x19, x0 + + // SP pointer mangling (see glibc setjmp) + adrp x2, :got:__pointer_chk_guard + ldr x2, [x2, #:got_lo12:__pointer_chk_guard] + add x0, x29, 32 + ldr x2, [x2] + eor x1, x2, x0 + + // call tsan interceptor + bl __tsan_setjmp + + // restore env parameter + mov w1, w20 + mov x0, x19 + ldp x19, x20, [sp, 16] + ldp x29, x30, [sp], 32 + CFI_RESTORE (30) + CFI_RESTORE (29) + CFI_RESTORE (19) + CFI_RESTORE (20) + CFI_DEF_CFA (31, 0) + + // tail jump to libc sigsetjmp + adrp x2, :got:_ZN14__interception14real_sigsetjmpE + ldr x2, [x2, #:got_lo12:_ZN14__interception14real_sigsetjmpE] + ldr x2, [x2] + br x2 + CFI_ENDPROC +.size sigsetjmp, .-sigsetjmp + +.comm _ZN14__interception16real___sigsetjmpE,8,8 +.globl __sigsetjmp +.type __sigsetjmp, @function +__sigsetjmp: + CFI_STARTPROC + + // save env parameters for function call + stp x29, x30, [sp, -32]! + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (29, -32) + CFI_OFFSET (30, -24) + + // Adjust the SP for previous frame + add x29, sp, 0 + CFI_DEF_CFA_REGISTER (29) + + // Save jmp_buf and savesigs + stp x19, x20, [sp, 16] + CFI_OFFSET (19, -16) + CFI_OFFSET (20, -8) + mov w20, w1 + mov x19, x0 + + // SP pointer mangling (see glibc setjmp) + adrp x2, :got:__pointer_chk_guard + ldr x2, [x2, #:got_lo12:__pointer_chk_guard] + add x0, x29, 32 + ldr x2, [x2] + eor x1, x2, x0 + + // call tsan interceptor + bl __tsan_setjmp + + mov w1, w20 + mov x0, x19 + ldp x19, x20, [sp, 16] + ldp x29, x30, [sp], 32 + CFI_RESTORE (30) + CFI_RESTORE (29) + CFI_RESTORE (19) + CFI_RESTORE (20) + CFI_DEF_CFA (31, 0) + + // tail jump to libc __sigsetjmp + adrp x2, :got:_ZN14__interception16real___sigsetjmpE + ldr x2, [x2, #:got_lo12:_ZN14__interception16real___sigsetjmpE] + ldr x2, [x2] + br x2 + CFI_ENDPROC +.size __sigsetjmp, .-__sigsetjmp + +#if defined(__linux__) +/* We do not need executable stack. */ +.section .note.GNU-stack,"",@progbits +#endif diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_amd64.S b/src/compiler-rt/lib/tsan/rtl/tsan_rtl_amd64.S index 8db62f9013..caa832375e 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_amd64.S +++ b/src/compiler-rt/lib/tsan/rtl/tsan_rtl_amd64.S @@ -1,9 +1,13 @@ #include "sanitizer_common/sanitizer_asm.h" +#if !defined(__APPLE__) .section .text +#else +.section __TEXT,__text +#endif -.hidden __tsan_trace_switch -.globl __tsan_trace_switch_thunk -__tsan_trace_switch_thunk: +ASM_HIDDEN(__tsan_trace_switch) +.globl ASM_TSAN_SYMBOL(__tsan_trace_switch_thunk) +ASM_TSAN_SYMBOL(__tsan_trace_switch_thunk): CFI_STARTPROC # Save scratch registers. push %rax @@ -42,7 +46,7 @@ __tsan_trace_switch_thunk: shr $4, %rsp # clear 4 lsb, align to 16 shl $4, %rsp - call __tsan_trace_switch + call ASM_TSAN_SYMBOL(__tsan_trace_switch) # Unalign stack frame back. mov %rbx, %rsp # restore the original rsp @@ -81,9 +85,9 @@ __tsan_trace_switch_thunk: ret CFI_ENDPROC -.hidden __tsan_report_race -.globl __tsan_report_race_thunk -__tsan_report_race_thunk: +ASM_HIDDEN(__tsan_report_race) +.globl ASM_TSAN_SYMBOL(__tsan_report_race_thunk) +ASM_TSAN_SYMBOL(__tsan_report_race_thunk): CFI_STARTPROC # Save scratch registers. push %rax @@ -122,7 +126,7 @@ __tsan_report_race_thunk: shr $4, %rsp # clear 4 lsb, align to 16 shl $4, %rsp - call __tsan_report_race + call ASM_TSAN_SYMBOL(__tsan_report_race) # Unalign stack frame back. mov %rbx, %rsp # restore the original rsp @@ -161,11 +165,13 @@ __tsan_report_race_thunk: ret CFI_ENDPROC -.hidden __tsan_setjmp +ASM_HIDDEN(__tsan_setjmp) +#if !defined(__APPLE__) .comm _ZN14__interception11real_setjmpE,8,8 -.globl setjmp -.type setjmp, @function -setjmp: +#endif +.globl ASM_TSAN_SYMBOL_INTERCEPTOR(setjmp) +ASM_TYPE_FUNCTION(ASM_TSAN_SYMBOL_INTERCEPTOR(setjmp)) +ASM_TSAN_SYMBOL_INTERCEPTOR(setjmp): CFI_STARTPROC // save env parameter push %rdi @@ -175,29 +181,38 @@ setjmp: #if defined(__FreeBSD__) lea 8(%rsp), %rdi mov %rdi, %rsi -#else +#elif defined(__APPLE__) + lea 16(%rsp), %rdi + mov %rdi, %rsi +#elif defined(__linux__) lea 16(%rsp), %rdi mov %rdi, %rsi xor %fs:0x30, %rsi // magic mangling of rsp (see libc setjmp) rol $0x11, %rsi +#else +# error "Unknown platform" #endif // call tsan interceptor - call __tsan_setjmp + call ASM_TSAN_SYMBOL(__tsan_setjmp) // restore env parameter pop %rdi CFI_ADJUST_CFA_OFFSET(-8) CFI_RESTORE(%rdi) // tail jump to libc setjmp movl $0, %eax +#if !defined(__APPLE__) movq _ZN14__interception11real_setjmpE@GOTPCREL(%rip), %rdx jmp *(%rdx) +#else + jmp ASM_TSAN_SYMBOL(setjmp) +#endif CFI_ENDPROC -.size setjmp, .-setjmp +ASM_SIZE(ASM_TSAN_SYMBOL_INTERCEPTOR(setjmp)) .comm _ZN14__interception12real__setjmpE,8,8 -.globl _setjmp -.type _setjmp, @function -_setjmp: +.globl ASM_TSAN_SYMBOL_INTERCEPTOR(_setjmp) +ASM_TYPE_FUNCTION(ASM_TSAN_SYMBOL_INTERCEPTOR(_setjmp)) +ASM_TSAN_SYMBOL_INTERCEPTOR(_setjmp): CFI_STARTPROC // save env parameter push %rdi @@ -207,29 +222,38 @@ _setjmp: #if defined(__FreeBSD__) lea 8(%rsp), %rdi mov %rdi, %rsi -#else +#elif defined(__APPLE__) + lea 16(%rsp), %rdi + mov %rdi, %rsi +#elif defined(__linux__) lea 16(%rsp), %rdi mov %rdi, %rsi xor %fs:0x30, %rsi // magic mangling of rsp (see libc setjmp) rol $0x11, %rsi +#else +# error "Unknown platform" #endif // call tsan interceptor - call __tsan_setjmp + call ASM_TSAN_SYMBOL(__tsan_setjmp) // restore env parameter pop %rdi CFI_ADJUST_CFA_OFFSET(-8) CFI_RESTORE(%rdi) // tail jump to libc setjmp movl $0, %eax +#if !defined(__APPLE__) movq _ZN14__interception12real__setjmpE@GOTPCREL(%rip), %rdx jmp *(%rdx) +#else + jmp ASM_TSAN_SYMBOL(_setjmp) +#endif CFI_ENDPROC -.size _setjmp, .-_setjmp +ASM_SIZE(ASM_TSAN_SYMBOL_INTERCEPTOR(_setjmp)) .comm _ZN14__interception14real_sigsetjmpE,8,8 -.globl sigsetjmp -.type sigsetjmp, @function -sigsetjmp: +.globl ASM_TSAN_SYMBOL_INTERCEPTOR(sigsetjmp) +ASM_TYPE_FUNCTION(ASM_TSAN_SYMBOL_INTERCEPTOR(sigsetjmp)) +ASM_TSAN_SYMBOL_INTERCEPTOR(sigsetjmp): CFI_STARTPROC // save env parameter push %rdi @@ -246,14 +270,19 @@ sigsetjmp: #if defined(__FreeBSD__) lea 24(%rsp), %rdi mov %rdi, %rsi -#else +#elif defined(__APPLE__) + lea 32(%rsp), %rdi + mov %rdi, %rsi +#elif defined(__linux__) lea 32(%rsp), %rdi mov %rdi, %rsi xor %fs:0x30, %rsi // magic mangling of rsp (see libc setjmp) rol $0x11, %rsi +#else +# error "Unknown platform" #endif // call tsan interceptor - call __tsan_setjmp + call ASM_TSAN_SYMBOL(__tsan_setjmp) // unalign stack frame add $8, %rsp CFI_ADJUST_CFA_OFFSET(-8) @@ -267,15 +296,20 @@ sigsetjmp: CFI_RESTORE(%rdi) // tail jump to libc sigsetjmp movl $0, %eax +#if !defined(__APPLE__) movq _ZN14__interception14real_sigsetjmpE@GOTPCREL(%rip), %rdx jmp *(%rdx) +#else + jmp ASM_TSAN_SYMBOL(sigsetjmp) +#endif CFI_ENDPROC -.size sigsetjmp, .-sigsetjmp +ASM_SIZE(ASM_TSAN_SYMBOL_INTERCEPTOR(sigsetjmp)) +#if !defined(__APPLE__) .comm _ZN14__interception16real___sigsetjmpE,8,8 -.globl __sigsetjmp -.type __sigsetjmp, @function -__sigsetjmp: +.globl ASM_TSAN_SYMBOL_INTERCEPTOR(__sigsetjmp) +ASM_TYPE_FUNCTION(ASM_TSAN_SYMBOL_INTERCEPTOR(__sigsetjmp)) +ASM_TSAN_SYMBOL_INTERCEPTOR(__sigsetjmp): CFI_STARTPROC // save env parameter push %rdi @@ -299,7 +333,7 @@ __sigsetjmp: rol $0x11, %rsi #endif // call tsan interceptor - call __tsan_setjmp + call ASM_TSAN_SYMBOL(__tsan_setjmp) // unalign stack frame add $8, %rsp CFI_ADJUST_CFA_OFFSET(-8) @@ -316,7 +350,8 @@ __sigsetjmp: movq _ZN14__interception16real___sigsetjmpE@GOTPCREL(%rip), %rdx jmp *(%rdx) CFI_ENDPROC -.size __sigsetjmp, .-__sigsetjmp +ASM_SIZE(ASM_TSAN_SYMBOL_INTERCEPTOR(__sigsetjmp)) +#endif // !defined(__APPLE__) #if defined(__FreeBSD__) || defined(__linux__) /* We do not need executable stack. */ diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_ppc64.S b/src/compiler-rt/lib/tsan/rtl/tsan_rtl_ppc64.S new file mode 100644 index 0000000000..8285e21aa1 --- /dev/null +++ b/src/compiler-rt/lib/tsan/rtl/tsan_rtl_ppc64.S @@ -0,0 +1,288 @@ +#include "tsan_ppc_regs.h" + + .section .text + .hidden __tsan_setjmp + .globl _setjmp + .type _setjmp, @function + .align 4 +#if _CALL_ELF == 2 +_setjmp: +#else + .section ".opd","aw" + .align 3 +_setjmp: + .quad .L._setjmp,.TOC.@tocbase,0 + .previous +#endif +.L._setjmp: + mflr r0 + stdu r1,-48(r1) + std r2,24(r1) + std r3,32(r1) + std r0,40(r1) + // r3 is the original stack pointer. + addi r3,r1,48 + // r4 is the mangled stack pointer (see glibc) + ld r4,-28696(r13) + xor r4,r3,r4 + // Materialize a TOC in case we were called from libc. + // For big-endian, we load the TOC from the OPD. For little- + // endian, we use the .TOC. symbol to find it. + nop + bcl 20,31,0f +0: + mflr r2 +#if _CALL_ELF == 2 + addis r2,r2,.TOC.-0b@ha + addi r2,r2,.TOC.-0b@l +#else + addis r2,r2,_setjmp-0b@ha + addi r2,r2,_setjmp-0b@l + ld r2,8(r2) +#endif + // Call the interceptor. + bl __tsan_setjmp + nop + // Restore regs needed for setjmp. + ld r3,32(r1) + ld r0,40(r1) + // Emulate the real setjmp function. We do this because we can't + // perform a sibcall: The real setjmp function trashes the TOC + // pointer, and with a sibcall we have no way to restore it. + // This way we can make sure our caller's stack pointer and + // link register are saved correctly in the jmpbuf. + ld r6,-28696(r13) + addi r5,r1,48 // original stack ptr of caller + xor r5,r6,r5 + std r5,0(r3) // mangled stack ptr of caller + ld r5,24(r1) + std r5,8(r3) // caller's saved TOC pointer + xor r0,r6,r0 + std r0,16(r3) // caller's mangled return address + mfcr r0 + // Nonvolatiles. + std r14,24(r3) + stfd f14,176(r3) + stw r0,172(r3) // CR + std r15,32(r3) + stfd f15,184(r3) + std r16,40(r3) + stfd f16,192(r3) + std r17,48(r3) + stfd f17,200(r3) + std r18,56(r3) + stfd f18,208(r3) + std r19,64(r3) + stfd f19,216(r3) + std r20,72(r3) + stfd f20,224(r3) + std r21,80(r3) + stfd f21,232(r3) + std r22,88(r3) + stfd f22,240(r3) + std r23,96(r3) + stfd f23,248(r3) + std r24,104(r3) + stfd f24,256(r3) + std r25,112(r3) + stfd f25,264(r3) + std r26,120(r3) + stfd f26,272(r3) + std r27,128(r3) + stfd f27,280(r3) + std r28,136(r3) + stfd f28,288(r3) + std r29,144(r3) + stfd f29,296(r3) + std r30,152(r3) + stfd f30,304(r3) + std r31,160(r3) + stfd f31,312(r3) + addi r5,r3,320 + mfspr r0,256 + stw r0,168(r3) // VRSAVE + addi r6,r5,16 + stvx v20,0,r5 + addi r5,r5,32 + stvx v21,0,r6 + addi r6,r6,32 + stvx v22,0,r5 + addi r5,r5,32 + stvx v23,0,r6 + addi r6,r6,32 + stvx v24,0,r5 + addi r5,r5,32 + stvx v25,0,r6 + addi r6,r6,32 + stvx v26,0,r5 + addi r5,r5,32 + stvx v27,0,r6 + addi r6,r6,32 + stvx v28,0,r5 + addi r5,r5,32 + stvx v29,0,r6 + addi r6,r6,32 + stvx v30,0,r5 + stvx v31,0,r6 + // Clear the "mask-saved" slot. + li r4,0 + stw r4,512(r3) + // Restore TOC, LR, and stack and return to caller. + ld r2,24(r1) + ld r0,40(r1) + addi r1,r1,48 + li r3,0 // This is the setjmp return path + mtlr r0 + blr + .size _setjmp, .-.L._setjmp + + .globl setjmp + .type setjmp, @function + .align 4 +setjmp: + b _setjmp + .size setjmp, .-setjmp + + // sigsetjmp is like setjmp, except that the mask in r4 needs + // to be saved at offset 512 of the jump buffer. + .globl __sigsetjmp + .type __sigsetjmp, @function + .align 4 +#if _CALL_ELF == 2 +__sigsetjmp: +#else + .section ".opd","aw" + .align 3 +__sigsetjmp: + .quad .L.__sigsetjmp,.TOC.@tocbase,0 + .previous +#endif +.L.__sigsetjmp: + mflr r0 + stdu r1,-64(r1) + std r2,24(r1) + std r3,32(r1) + std r4,40(r1) + std r0,48(r1) + // r3 is the original stack pointer. + addi r3,r1,64 + // r4 is the mangled stack pointer (see glibc) + ld r4,-28696(r13) + xor r4,r3,r4 + // Materialize a TOC in case we were called from libc. + // For big-endian, we load the TOC from the OPD. For little- + // endian, we use the .TOC. symbol to find it. + nop + bcl 20,31,1f +1: + mflr r2 +#if _CALL_ELF == 2 + addis r2,r2,.TOC.-1b@ha + addi r2,r2,.TOC.-1b@l +#else + addis r2,r2,_setjmp-1b@ha + addi r2,r2,_setjmp-1b@l + ld r2,8(r2) +#endif + // Call the interceptor. + bl __tsan_setjmp + nop + // Restore regs needed for __sigsetjmp. + ld r3,32(r1) + ld r4,40(r1) + ld r0,48(r1) + // Emulate the real sigsetjmp function. We do this because we can't + // perform a sibcall: The real sigsetjmp function trashes the TOC + // pointer, and with a sibcall we have no way to restore it. + // This way we can make sure our caller's stack pointer and + // link register are saved correctly in the jmpbuf. + ld r6,-28696(r13) + addi r5,r1,64 // original stack ptr of caller + xor r5,r6,r5 + std r5,0(r3) // mangled stack ptr of caller + ld r5,24(r1) + std r5,8(r3) // caller's saved TOC pointer + xor r0,r6,r0 + std r0,16(r3) // caller's mangled return address + mfcr r0 + // Nonvolatiles. + std r14,24(r3) + stfd f14,176(r3) + stw r0,172(r3) // CR + std r15,32(r3) + stfd f15,184(r3) + std r16,40(r3) + stfd f16,192(r3) + std r17,48(r3) + stfd f17,200(r3) + std r18,56(r3) + stfd f18,208(r3) + std r19,64(r3) + stfd f19,216(r3) + std r20,72(r3) + stfd f20,224(r3) + std r21,80(r3) + stfd f21,232(r3) + std r22,88(r3) + stfd f22,240(r3) + std r23,96(r3) + stfd f23,248(r3) + std r24,104(r3) + stfd f24,256(r3) + std r25,112(r3) + stfd f25,264(r3) + std r26,120(r3) + stfd f26,272(r3) + std r27,128(r3) + stfd f27,280(r3) + std r28,136(r3) + stfd f28,288(r3) + std r29,144(r3) + stfd f29,296(r3) + std r30,152(r3) + stfd f30,304(r3) + std r31,160(r3) + stfd f31,312(r3) + addi r5,r3,320 + mfspr r0,256 + stw r0,168(r3) // VRSAVE + addi r6,r5,16 + stvx v20,0,r5 + addi r5,r5,32 + stvx v21,0,r6 + addi r6,r6,32 + stvx v22,0,r5 + addi r5,r5,32 + stvx v23,0,r6 + addi r6,r6,32 + stvx v24,0,r5 + addi r5,r5,32 + stvx v25,0,r6 + addi r6,r6,32 + stvx v26,0,r5 + addi r5,r5,32 + stvx v27,0,r6 + addi r6,r6,32 + stvx v28,0,r5 + addi r5,r5,32 + stvx v29,0,r6 + addi r6,r6,32 + stvx v30,0,r5 + stvx v31,0,r6 + // Save into the "mask-saved" slot. + stw r4,512(r3) + // Restore TOC, LR, and stack and return to caller. + ld r2,24(r1) + ld r0,48(r1) + addi r1,r1,64 + li r3,0 // This is the sigsetjmp return path + mtlr r0 + blr + .size __sigsetjmp, .-.L.__sigsetjmp + + .globl sigsetjmp + .type sigsetjmp, @function + .align 4 +sigsetjmp: + b __sigsetjmp + .size sigsetjmp, .-sigsetjmp diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/src/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc index 7e906e5d76..5aff6ca56a 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc @@ -49,8 +49,8 @@ void TsanCheckFailed(const char *file, int line, const char *cond, #ifdef TSAN_EXTERNAL_HOOKS bool OnReport(const ReportDesc *rep, bool suppressed); #else -SANITIZER_INTERFACE_ATTRIBUTE -bool WEAK OnReport(const ReportDesc *rep, bool suppressed) { +SANITIZER_WEAK_CXX_DEFAULT_IMPL +bool OnReport(const ReportDesc *rep, bool suppressed) { (void)rep; return suppressed; } @@ -186,7 +186,7 @@ void ScopedReport::AddThread(const ThreadContext *tctx, bool suppressable) { return; } void *mem = internal_alloc(MBlockReportThread, sizeof(ReportThread)); - ReportThread *rt = new(mem) ReportThread(); + ReportThread *rt = new(mem) ReportThread; rep_->threads.PushBack(rt); rt->id = tctx->tid; rt->pid = tctx->os_id; @@ -200,16 +200,16 @@ void ScopedReport::AddThread(const ThreadContext *tctx, bool suppressable) { } #ifndef SANITIZER_GO +static bool FindThreadByUidLockedCallback(ThreadContextBase *tctx, void *arg) { + int unique_id = *(int *)arg; + return tctx->unique_id == (u32)unique_id; +} + static ThreadContext *FindThreadByUidLocked(int unique_id) { ctx->thread_registry->CheckLocked(); - for (unsigned i = 0; i < kMaxTid; i++) { - ThreadContext *tctx = static_cast( - ctx->thread_registry->GetThreadLocked(i)); - if (tctx && tctx->unique_id == (u32)unique_id) { - return tctx; - } - } - return 0; + return static_cast( + ctx->thread_registry->FindThreadContextLocked( + FindThreadByUidLockedCallback, &unique_id)); } static ThreadContext *FindThreadByTidLocked(int tid) { @@ -256,7 +256,7 @@ void ScopedReport::AddMutex(const SyncVar *s) { return; } void *mem = internal_alloc(MBlockReportMutex, sizeof(ReportMutex)); - ReportMutex *rm = new(mem) ReportMutex(); + ReportMutex *rm = new(mem) ReportMutex; rep_->mutexes.PushBack(rm); rm->id = s->uid; rm->addr = s->addr; @@ -289,7 +289,7 @@ void ScopedReport::AddDeadMutex(u64 id) { return; } void *mem = internal_alloc(MBlockReportMutex, sizeof(ReportMutex)); - ReportMutex *rm = new(mem) ReportMutex(); + ReportMutex *rm = new(mem) ReportMutex; rep_->mutexes.PushBack(rm); rm->id = id; rm->addr = 0; diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc b/src/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc index 1228c0a188..b992d78f8c 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc @@ -34,7 +34,8 @@ static const char *const std_suppressions = "race:std::_Sp_counted_ptr_inplacehit_count, matched[i]->type, - matched[i]->templ); + Printf("%d %s:%s\n", atomic_load_relaxed(&matched[i]->hit_count), + matched[i]->type, matched[i]->templ); } } } // namespace __tsan diff --git a/src/compiler-rt/lib/tsan/rtl/tsan_symbolize.cc b/src/compiler-rt/lib/tsan/rtl/tsan_symbolize.cc index a6b9bca050..b242395179 100644 --- a/src/compiler-rt/lib/tsan/rtl/tsan_symbolize.cc +++ b/src/compiler-rt/lib/tsan/rtl/tsan_symbolize.cc @@ -38,10 +38,10 @@ void ExitSymbolizer() { // May be overriden by JIT/JAVA/etc, // whatever produces PCs marked with kExternalPCBit. -extern "C" bool WEAK __tsan_symbolize_external(uptr pc, - char *func_buf, uptr func_siz, - char *file_buf, uptr file_siz, - int *line, int *col) { +SANITIZER_WEAK_DEFAULT_IMPL +bool __tsan_symbolize_external(uptr pc, char *func_buf, uptr func_siz, + char *file_buf, uptr file_siz, int *line, + int *col) { return false; } @@ -71,7 +71,7 @@ ReportLocation *SymbolizeData(uptr addr) { if (!Symbolizer::GetOrInit()->SymbolizeData(addr, &info)) return 0; ReportLocation *ent = ReportLocation::New(ReportLocationGlobal); - ent->global = info; + internal_memcpy(&ent->global, &info, sizeof(info)); return ent; } diff --git a/src/compiler-rt/lib/tsan/tests/CMakeLists.txt b/src/compiler-rt/lib/tsan/tests/CMakeLists.txt index 1c3f98f3f0..51181bab3a 100644 --- a/src/compiler-rt/lib/tsan/tests/CMakeLists.txt +++ b/src/compiler-rt/lib/tsan/tests/CMakeLists.txt @@ -33,9 +33,12 @@ macro(tsan_compile obj_list source arch) endmacro() macro(add_tsan_unittest testname) - # Build unit tests only for 64-bit Linux. - if(UNIX AND NOT APPLE) - foreach(arch ${TSAN_SUPPORTED_ARCH}) + set(TSAN_TEST_ARCH ${TSAN_SUPPORTED_ARCH}) + if(APPLE) + darwin_filter_host_archs(TSAN_SUPPORTED_ARCH TSAN_TEST_ARCH) + endif() + if(UNIX) + foreach(arch ${TSAN_TEST_ARCH}) cmake_parse_arguments(TEST "" "" "SOURCES;HEADERS" ${ARGN}) set(TEST_OBJECTS) foreach(SOURCE ${TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE}) @@ -46,15 +49,38 @@ macro(add_tsan_unittest testname) if(NOT COMPILER_RT_STANDALONE_BUILD) list(APPEND TEST_DEPS tsan) endif() - # FIXME: Looks like we should link TSan with just-built runtime, - # and not rely on -fsanitize=thread, as these tests are essentially - # unit tests. - add_compiler_rt_test(TsanUnitTests ${testname} - OBJECTS ${TEST_OBJECTS} - DEPS ${TEST_DEPS} - LINK_FLAGS ${TARGET_LINK_FLAGS} - -fsanitize=thread - -lstdc++ -lm) + if(NOT APPLE) + # FIXME: Looks like we should link TSan with just-built runtime, + # and not rely on -fsanitize=thread, as these tests are essentially + # unit tests. + add_compiler_rt_test(TsanUnitTests ${testname} + OBJECTS ${TEST_OBJECTS} + DEPS ${TEST_DEPS} + LINK_FLAGS ${TARGET_LINK_FLAGS} + -fsanitize=thread + -lstdc++ -lm) + else() + set(TSAN_TEST_RUNTIME_OBJECTS + $ + $ + $ + $ + $) + set(TSAN_TEST_RUNTIME RTTsanTest.${testname}.${arch}) + add_library(${TSAN_TEST_RUNTIME} STATIC ${TSAN_TEST_RUNTIME_OBJECTS}) + set_target_properties(${TSAN_TEST_RUNTIME} PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + list(APPEND TEST_OBJECTS lib${TSAN_TEST_RUNTIME}.a) + list(APPEND TEST_DEPS ${TSAN_TEST_RUNTIME}) + # Intentionally do *not* link with `-fsanitize=thread`. We already link + # against a static version of the runtime, and we don't want the dynamic + # one. + add_compiler_rt_test(TsanUnitTests "${testname}-${arch}-Test" + OBJECTS ${TEST_OBJECTS} + DEPS ${TEST_DEPS} + LINK_FLAGS ${TARGET_LINK_FLAGS} + -lc++) + endif() endforeach() endif() endmacro() diff --git a/src/compiler-rt/lib/tsan/tests/rtl/CMakeLists.txt b/src/compiler-rt/lib/tsan/tests/rtl/CMakeLists.txt index 989566d9e0..a34f08ea96 100644 --- a/src/compiler-rt/lib/tsan/tests/rtl/CMakeLists.txt +++ b/src/compiler-rt/lib/tsan/tests/rtl/CMakeLists.txt @@ -7,8 +7,8 @@ set(TSAN_RTL_TEST_SOURCES tsan_test.cc tsan_thread.cc) -if(UNIX AND NOT APPLE) - list(APPEND TSAN_RTL_TEST_SOURCES tsan_test_util_linux.cc) +if(UNIX) + list(APPEND TSAN_RTL_TEST_SOURCES tsan_test_util_posix.cc) endif() set(TSAN_RTL_TEST_HEADERS diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc b/src/compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc index 71fb05c228..e1a61b5e43 100644 --- a/src/compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc +++ b/src/compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc @@ -35,7 +35,7 @@ static void thread_secific_dtor(void *v) { __tsan_write4(&k->cnt); EXPECT_EQ(pthread_mutex_unlock(k->mtx), 0); if (k->val == 42) { - delete k; + // Okay. } else if (k->val == 43 || k->val == 44) { k->val--; EXPECT_EQ(pthread_setspecific(k->key, k), 0); @@ -57,14 +57,13 @@ TEST(Posix, ThreadSpecificDtors) { pthread_mutex_t mtx; EXPECT_EQ(pthread_mutex_init(&mtx, 0), 0); pthread_t th[3]; - thread_key *k[3]; - k[0] = new thread_key(key, &mtx, 42, &cnt); - k[1] = new thread_key(key, &mtx, 43, &cnt); - k[2] = new thread_key(key, &mtx, 44, &cnt); - EXPECT_EQ(pthread_create(&th[0], 0, dtors_thread, k[0]), 0); - EXPECT_EQ(pthread_create(&th[1], 0, dtors_thread, k[1]), 0); + thread_key k1 = thread_key(key, &mtx, 42, &cnt); + thread_key k2 = thread_key(key, &mtx, 43, &cnt); + thread_key k3 = thread_key(key, &mtx, 44, &cnt); + EXPECT_EQ(pthread_create(&th[0], 0, dtors_thread, &k1), 0); + EXPECT_EQ(pthread_create(&th[1], 0, dtors_thread, &k2), 0); EXPECT_EQ(pthread_join(th[0], 0), 0); - EXPECT_EQ(pthread_create(&th[2], 0, dtors_thread, k[2]), 0); + EXPECT_EQ(pthread_create(&th[2], 0, dtors_thread, &k3), 0); EXPECT_EQ(pthread_join(th[1], 0), 0); EXPECT_EQ(pthread_join(th[2], 0), 0); EXPECT_EQ(pthread_key_delete(key), 0); diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_test.cc b/src/compiler-rt/lib/tsan/tests/rtl/tsan_test.cc index b8b9555c2b..edfede078b 100644 --- a/src/compiler-rt/lib/tsan/tests/rtl/tsan_test.cc +++ b/src/compiler-rt/lib/tsan/tests/rtl/tsan_test.cc @@ -47,6 +47,13 @@ int run_tests(int argc, char **argv) { const char *argv0; +#ifdef __APPLE__ +// On Darwin, turns off symbolication and crash logs to make tests faster. +extern "C" const char* __tsan_default_options() { + return "symbolize=false:abort_on_error=0"; +} +#endif + int main(int argc, char **argv) { argv0 = argv[0]; return run_tests(argc, argv); diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util.h b/src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util.h index 84d277b137..31b1b188f6 100644 --- a/src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util.h +++ b/src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util.h @@ -31,7 +31,15 @@ class MemLoc { class Mutex { public: - enum Type { Normal, Spin, RW }; + enum Type { + Normal, + RW, +#ifndef __APPLE__ + Spin +#else + Spin = Normal +#endif + }; explicit Mutex(Type type = Normal); ~Mutex(); diff --git a/src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_linux.cc b/src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cc similarity index 70% rename from src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_linux.cc rename to src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cc index 9298bf051a..c8be088d26 100644 --- a/src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_linux.cc +++ b/src/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cc @@ -1,5 +1,4 @@ - -//===-- tsan_test_util_linux.cc -------------------------------------------===// +//===-- tsan_test_util_posix.cc -------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -10,7 +9,7 @@ // // This file is a part of ThreadSanitizer (TSan), a race detector. // -// Test utils, Linux and FreeBSD implementation. +// Test utils, Linux, FreeBSD and Darwin implementation. //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_atomic.h" @@ -34,8 +33,51 @@ static __thread bool expect_report; static __thread bool expect_report_reported; static __thread ReportType expect_report_type; -extern "C" void *__interceptor_memcpy(void*, const void*, uptr); -extern "C" void *__interceptor_memset(void*, int, uptr); +#ifdef __APPLE__ +#define __interceptor_memcpy wrap_memcpy +#define __interceptor_memset wrap_memset +#define __interceptor_pthread_create wrap_pthread_create +#define __interceptor_pthread_join wrap_pthread_join +#define __interceptor_pthread_detach wrap_pthread_detach +#define __interceptor_pthread_mutex_init wrap_pthread_mutex_init +#define __interceptor_pthread_mutex_lock wrap_pthread_mutex_lock +#define __interceptor_pthread_mutex_unlock wrap_pthread_mutex_unlock +#define __interceptor_pthread_mutex_destroy wrap_pthread_mutex_destroy +#define __interceptor_pthread_mutex_trylock wrap_pthread_mutex_trylock +#define __interceptor_pthread_rwlock_init wrap_pthread_rwlock_init +#define __interceptor_pthread_rwlock_destroy wrap_pthread_rwlock_destroy +#define __interceptor_pthread_rwlock_trywrlock wrap_pthread_rwlock_trywrlock +#define __interceptor_pthread_rwlock_wrlock wrap_pthread_rwlock_wrlock +#define __interceptor_pthread_rwlock_unlock wrap_pthread_rwlock_unlock +#define __interceptor_pthread_rwlock_rdlock wrap_pthread_rwlock_rdlock +#define __interceptor_pthread_rwlock_tryrdlock wrap_pthread_rwlock_tryrdlock +#endif + +extern "C" void *__interceptor_memcpy(void *, const void *, uptr); +extern "C" void *__interceptor_memset(void *, int, uptr); +extern "C" int __interceptor_pthread_create(pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), + void *arg); +extern "C" int __interceptor_pthread_join(pthread_t thread, void **value_ptr); +extern "C" int __interceptor_pthread_detach(pthread_t thread); + +extern "C" int __interceptor_pthread_mutex_init( + pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); +extern "C" int __interceptor_pthread_mutex_lock(pthread_mutex_t *mutex); +extern "C" int __interceptor_pthread_mutex_unlock(pthread_mutex_t *mutex); +extern "C" int __interceptor_pthread_mutex_destroy(pthread_mutex_t *mutex); +extern "C" int __interceptor_pthread_mutex_trylock(pthread_mutex_t *mutex); + +extern "C" int __interceptor_pthread_rwlock_init( + pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); +extern "C" int __interceptor_pthread_rwlock_destroy(pthread_rwlock_t *rwlock); +extern "C" int __interceptor_pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); +extern "C" int __interceptor_pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); +extern "C" int __interceptor_pthread_rwlock_unlock(pthread_rwlock_t *rwlock); +extern "C" int __interceptor_pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); +extern "C" int __interceptor_pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); + static void *BeforeInitThread(void *param) { (void)param; @@ -48,12 +90,12 @@ static void AtExit() { void TestMutexBeforeInit() { // Mutexes must be usable before __tsan_init(); pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&mtx); - pthread_mutex_unlock(&mtx); - pthread_mutex_destroy(&mtx); + __interceptor_pthread_mutex_lock(&mtx); + __interceptor_pthread_mutex_unlock(&mtx); + __interceptor_pthread_mutex_destroy(&mtx); pthread_t thr; - pthread_create(&thr, 0, BeforeInitThread, 0); - pthread_join(thr, 0); + __interceptor_pthread_create(&thr, 0, BeforeInitThread, 0); + __interceptor_pthread_join(thr, 0); atexit(AtExit); } @@ -105,11 +147,13 @@ void Mutex::Init() { CHECK(!alive_); alive_ = true; if (type_ == Normal) - CHECK_EQ(pthread_mutex_init((pthread_mutex_t*)mtx_, 0), 0); + CHECK_EQ(__interceptor_pthread_mutex_init((pthread_mutex_t*)mtx_, 0), 0); +#ifndef __APPLE__ else if (type_ == Spin) CHECK_EQ(pthread_spin_init((pthread_spinlock_t*)mtx_, 0), 0); +#endif else if (type_ == RW) - CHECK_EQ(pthread_rwlock_init((pthread_rwlock_t*)mtx_, 0), 0); + CHECK_EQ(__interceptor_pthread_rwlock_init((pthread_rwlock_t*)mtx_, 0), 0); else CHECK(0); } @@ -126,60 +170,68 @@ void Mutex::Destroy() { CHECK(alive_); alive_ = false; if (type_ == Normal) - CHECK_EQ(pthread_mutex_destroy((pthread_mutex_t*)mtx_), 0); + CHECK_EQ(__interceptor_pthread_mutex_destroy((pthread_mutex_t*)mtx_), 0); +#ifndef __APPLE__ else if (type_ == Spin) CHECK_EQ(pthread_spin_destroy((pthread_spinlock_t*)mtx_), 0); +#endif else if (type_ == RW) - CHECK_EQ(pthread_rwlock_destroy((pthread_rwlock_t*)mtx_), 0); + CHECK_EQ(__interceptor_pthread_rwlock_destroy((pthread_rwlock_t*)mtx_), 0); } void Mutex::Lock() { CHECK(alive_); if (type_ == Normal) - CHECK_EQ(pthread_mutex_lock((pthread_mutex_t*)mtx_), 0); + CHECK_EQ(__interceptor_pthread_mutex_lock((pthread_mutex_t*)mtx_), 0); +#ifndef __APPLE__ else if (type_ == Spin) CHECK_EQ(pthread_spin_lock((pthread_spinlock_t*)mtx_), 0); +#endif else if (type_ == RW) - CHECK_EQ(pthread_rwlock_wrlock((pthread_rwlock_t*)mtx_), 0); + CHECK_EQ(__interceptor_pthread_rwlock_wrlock((pthread_rwlock_t*)mtx_), 0); } bool Mutex::TryLock() { CHECK(alive_); if (type_ == Normal) - return pthread_mutex_trylock((pthread_mutex_t*)mtx_) == 0; + return __interceptor_pthread_mutex_trylock((pthread_mutex_t*)mtx_) == 0; +#ifndef __APPLE__ else if (type_ == Spin) return pthread_spin_trylock((pthread_spinlock_t*)mtx_) == 0; +#endif else if (type_ == RW) - return pthread_rwlock_trywrlock((pthread_rwlock_t*)mtx_) == 0; + return __interceptor_pthread_rwlock_trywrlock((pthread_rwlock_t*)mtx_) == 0; return false; } void Mutex::Unlock() { CHECK(alive_); if (type_ == Normal) - CHECK_EQ(pthread_mutex_unlock((pthread_mutex_t*)mtx_), 0); + CHECK_EQ(__interceptor_pthread_mutex_unlock((pthread_mutex_t*)mtx_), 0); +#ifndef __APPLE__ else if (type_ == Spin) CHECK_EQ(pthread_spin_unlock((pthread_spinlock_t*)mtx_), 0); +#endif else if (type_ == RW) - CHECK_EQ(pthread_rwlock_unlock((pthread_rwlock_t*)mtx_), 0); + CHECK_EQ(__interceptor_pthread_rwlock_unlock((pthread_rwlock_t*)mtx_), 0); } void Mutex::ReadLock() { CHECK(alive_); CHECK(type_ == RW); - CHECK_EQ(pthread_rwlock_rdlock((pthread_rwlock_t*)mtx_), 0); + CHECK_EQ(__interceptor_pthread_rwlock_rdlock((pthread_rwlock_t*)mtx_), 0); } bool Mutex::TryReadLock() { CHECK(alive_); CHECK(type_ == RW); - return pthread_rwlock_tryrdlock((pthread_rwlock_t*)mtx_) == 0; + return __interceptor_pthread_rwlock_tryrdlock((pthread_rwlock_t*)mtx_) == 0; } void Mutex::ReadUnlock() { CHECK(alive_); CHECK(type_ == RW); - CHECK_EQ(pthread_rwlock_unlock((pthread_rwlock_t*)mtx_), 0); + CHECK_EQ(__interceptor_pthread_rwlock_unlock((pthread_rwlock_t*)mtx_), 0); } struct Event { @@ -263,7 +315,7 @@ void ScopedThread::Impl::HandleEvent(Event *ev) { } } CHECK_NE(tsan_mop, 0); -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__APPLE__) const int ErrCode = ESOCKTNOSUPPORT; #else const int ErrCode = ECHRNG; @@ -327,7 +379,7 @@ void *ScopedThread::Impl::ScopedThreadCallback(void *arg) { for (;;) { Event* ev = (Event*)atomic_load(&impl->event, memory_order_acquire); if (ev == 0) { - pthread_yield(); + sched_yield(); continue; } if (ev->type == Event::SHUTDOWN) { @@ -348,7 +400,7 @@ void ScopedThread::Impl::send(Event *e) { CHECK_EQ(atomic_load(&event, memory_order_relaxed), 0); atomic_store(&event, (uintptr_t)e, memory_order_release); while (atomic_load(&event, memory_order_acquire) != 0) - pthread_yield(); + sched_yield(); } } @@ -360,9 +412,10 @@ ScopedThread::ScopedThread(bool detached, bool main) { if (!main) { pthread_attr_t attr; pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, detached); + pthread_attr_setdetachstate( + &attr, detached ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE); pthread_attr_setstacksize(&attr, 64*1024); - pthread_create(&impl_->thread, &attr, + __interceptor_pthread_create(&impl_->thread, &attr, ScopedThread::Impl::ScopedThreadCallback, impl_); } } @@ -372,7 +425,7 @@ ScopedThread::~ScopedThread() { Event event(Event::SHUTDOWN); impl_->send(&event); if (!impl_->detached) - pthread_join(impl_->thread, 0); + __interceptor_pthread_join(impl_->thread, 0); } delete impl_; } @@ -381,7 +434,7 @@ void ScopedThread::Detach() { CHECK(!impl_->main); CHECK(!impl_->detached); impl_->detached = true; - pthread_detach(impl_->thread); + __interceptor_pthread_detach(impl_->thread); } void ScopedThread::Access(void *addr, bool is_write, diff --git a/src/compiler-rt/lib/tsan/tests/unit/tsan_clock_test.cc b/src/compiler-rt/lib/tsan/tests/unit/tsan_clock_test.cc index 92071827d3..83e25fb5a9 100644 --- a/src/compiler-rt/lib/tsan/tests/unit/tsan_clock_test.cc +++ b/src/compiler-rt/lib/tsan/tests/unit/tsan_clock_test.cc @@ -13,6 +13,7 @@ #include "tsan_clock.h" #include "tsan_rtl.h" #include "gtest/gtest.h" +#include #include namespace __tsan { @@ -416,9 +417,9 @@ static bool ClockFuzzer(bool printing) { } TEST(Clock, Fuzzer) { - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - int seed = ts.tv_sec + ts.tv_nsec; + struct timeval tv; + gettimeofday(&tv, NULL); + int seed = tv.tv_sec + tv.tv_usec; printf("seed=%d\n", seed); srand(seed); if (!ClockFuzzer(false)) { diff --git a/src/compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc b/src/compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc index bfaefe6487..609141c592 100644 --- a/src/compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc +++ b/src/compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc @@ -141,11 +141,13 @@ TEST(Mman, CallocOverflow) { // which is overflown by tsan memory accesses functions in debug mode. return; #endif + ThreadState *thr = cur_thread(); + uptr pc = 0; size_t kArraySize = 4096; volatile size_t kMaxSizeT = std::numeric_limits::max(); volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10; volatile void *p = NULL; - EXPECT_DEATH(p = calloc(kArraySize, kArraySize2), + EXPECT_DEATH(p = user_calloc(thr, pc, kArraySize, kArraySize2), "allocator is terminating the process instead of returning 0"); EXPECT_EQ(0L, p); } diff --git a/src/compiler-rt/lib/ubsan/ubsan_checks.inc b/src/compiler-rt/lib/ubsan/ubsan_checks.inc index dac479f514..6e08641405 100644 --- a/src/compiler-rt/lib/ubsan/ubsan_checks.inc +++ b/src/compiler-rt/lib/ubsan/ubsan_checks.inc @@ -14,40 +14,32 @@ # error "Define UBSAN_CHECK prior to including this file!" #endif -// UBSAN_CHECK(Name, SummaryKind, FlagName) -// SummaryKind and FlagName should be string literals. +// UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) +// SummaryKind and FSanitizeFlagName should be string literals. -UBSAN_CHECK(GenericUB, "undefined-behavior", "-fsanitize=undefined") -UBSAN_CHECK(NullPointerUse, "null-pointer-use", "-fsanitize=null") -UBSAN_CHECK(MisalignedPointerUse, "misaligned-pointer-use", - "-fsanitize=alignment") -UBSAN_CHECK(InsufficientObjectSize, "insufficient-object-size", - "-fsanitize=object-size") +UBSAN_CHECK(GenericUB, "undefined-behavior", "undefined") +UBSAN_CHECK(NullPointerUse, "null-pointer-use", "null") +UBSAN_CHECK(MisalignedPointerUse, "misaligned-pointer-use", "alignment") +UBSAN_CHECK(InsufficientObjectSize, "insufficient-object-size", "object-size") UBSAN_CHECK(SignedIntegerOverflow, "signed-integer-overflow", - "-fsanitize=signed-integer-overflow") + "signed-integer-overflow") UBSAN_CHECK(UnsignedIntegerOverflow, "unsigned-integer-overflow", - "-fsanitize=unsigned-integer-overflow") + "unsigned-integer-overflow") UBSAN_CHECK(IntegerDivideByZero, "integer-divide-by-zero", - "-fsanitize=integer-divide-by-zero") -UBSAN_CHECK(FloatDivideByZero, "float-divide-by-zero", - "-fsanitize=float-divide-by-zero") -UBSAN_CHECK(InvalidShiftBase, "invalid-shift-base", "-fsanitize=shift-base") -UBSAN_CHECK(InvalidShiftExponent, "invalid-shift-exponent", - "-fsanitize=shift-exponent") -UBSAN_CHECK(OutOfBoundsIndex, "out-of-bounds-index", "-fsanitize=bounds") -UBSAN_CHECK(UnreachableCall, "unreachable-call", "-fsanitize=unreachable") -UBSAN_CHECK(MissingReturn, "missing-return", "-fsanitize=return") -UBSAN_CHECK(NonPositiveVLAIndex, "non-positive-vla-index", - "-fsanitize=vla-bound") -UBSAN_CHECK(FloatCastOverflow, "float-cast-overflow", - "-fsanitize=float-cast-overflow") -UBSAN_CHECK(InvalidBoolLoad, "invalid-bool-load", "-fsanitize=bool") -UBSAN_CHECK(InvalidEnumLoad, "invalid-enum-load", "-fsanitize=enum") -UBSAN_CHECK(FunctionTypeMismatch, "function-type-mismatch", - "-fsanitize=function") + "integer-divide-by-zero") +UBSAN_CHECK(FloatDivideByZero, "float-divide-by-zero", "float-divide-by-zero") +UBSAN_CHECK(InvalidShiftBase, "invalid-shift-base", "shift-base") +UBSAN_CHECK(InvalidShiftExponent, "invalid-shift-exponent", "shift-exponent") +UBSAN_CHECK(OutOfBoundsIndex, "out-of-bounds-index", "bounds") +UBSAN_CHECK(UnreachableCall, "unreachable-call", "unreachable") +UBSAN_CHECK(MissingReturn, "missing-return", "return") +UBSAN_CHECK(NonPositiveVLAIndex, "non-positive-vla-index", "vla-bound") +UBSAN_CHECK(FloatCastOverflow, "float-cast-overflow", "float-cast-overflow") +UBSAN_CHECK(InvalidBoolLoad, "invalid-bool-load", "bool") +UBSAN_CHECK(InvalidEnumLoad, "invalid-enum-load", "enum") +UBSAN_CHECK(FunctionTypeMismatch, "function-type-mismatch", "function") UBSAN_CHECK(InvalidNullReturn, "invalid-null-return", - "-fsanitize=returns-nonnull-attribute") -UBSAN_CHECK(InvalidNullArgument, "invalid-null-argument", - "-fsanitize=nonnull-attribute") -UBSAN_CHECK(DynamicTypeMismatch, "dynamic-type-mismatch", "-fsanitize=vptr") -UBSAN_CHECK(CFIBadType, "cfi-bad-type", "-fsanitize=cfi") + "returns-nonnull-attribute") +UBSAN_CHECK(InvalidNullArgument, "invalid-null-argument", "nonnull-attribute") +UBSAN_CHECK(DynamicTypeMismatch, "dynamic-type-mismatch", "vptr") +UBSAN_CHECK(CFIBadType, "cfi-bad-type", "cfi") diff --git a/src/compiler-rt/lib/ubsan/ubsan_diag.cc b/src/compiler-rt/lib/ubsan/ubsan_diag.cc index 17e973cf6e..2476947dc9 100644 --- a/src/compiler-rt/lib/ubsan/ubsan_diag.cc +++ b/src/compiler-rt/lib/ubsan/ubsan_diag.cc @@ -45,7 +45,7 @@ static void MaybePrintStackTrace(uptr pc, uptr bp) { static const char *ConvertTypeToString(ErrorType Type) { switch (Type) { -#define UBSAN_CHECK(Name, SummaryKind, FlagName) \ +#define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) \ case ErrorType::Name: \ return SummaryKind; #include "ubsan_checks.inc" @@ -54,6 +54,17 @@ static const char *ConvertTypeToString(ErrorType Type) { UNREACHABLE("unknown ErrorType!"); } +static const char *ConvertTypeToFlagName(ErrorType Type) { + switch (Type) { +#define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) \ + case ErrorType::Name: \ + return FSanitizeFlagName; +#include "ubsan_checks.inc" +#undef UBSAN_CHECK + } + UNREACHABLE("unknown ErrorType!"); +} + static void MaybeReportErrorSummary(Location Loc, ErrorType Type) { if (!common_flags()->print_summary) return; @@ -365,14 +376,19 @@ ScopedReport::~ScopedReport() { MaybePrintStackTrace(Opts.pc, Opts.bp); MaybeReportErrorSummary(SummaryLoc, Type); CommonSanitizerReportMutex.Unlock(); - if (Opts.DieAfterReport || flags()->halt_on_error) + if (flags()->halt_on_error) Die(); } ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)]; static SuppressionContext *suppression_ctx = nullptr; static const char kVptrCheck[] = "vptr_check"; -static const char *kSuppressionTypes[] = { kVptrCheck }; +static const char *kSuppressionTypes[] = { +#define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) FSanitizeFlagName, +#include "ubsan_checks.inc" +#undef UBSAN_CHECK + kVptrCheck, +}; void __ubsan::InitializeSuppressions() { CHECK_EQ(nullptr, suppression_ctx); @@ -388,4 +404,28 @@ bool __ubsan::IsVptrCheckSuppressed(const char *TypeName) { return suppression_ctx->Match(TypeName, kVptrCheck, &s); } +bool __ubsan::IsPCSuppressed(ErrorType ET, uptr PC, const char *Filename) { + InitAsStandaloneIfNecessary(); + CHECK(suppression_ctx); + const char *SuppType = ConvertTypeToFlagName(ET); + // Fast path: don't symbolize PC if there is no suppressions for given UB + // type. + if (!suppression_ctx->HasSuppressionType(SuppType)) + return false; + Suppression *s = nullptr; + // Suppress by file name known to runtime. + if (Filename != nullptr && suppression_ctx->Match(Filename, SuppType, &s)) + return true; + // Suppress by module name. + if (const char *Module = Symbolizer::GetOrInit()->GetModuleNameForPc(PC)) { + if (suppression_ctx->Match(Module, SuppType, &s)) + return true; + } + // Suppress by function or source file name from debug info. + SymbolizedStackHolder Stack(Symbolizer::GetOrInit()->SymbolizePC(PC)); + const AddressInfo &AI = Stack.get()->info; + return suppression_ctx->Match(AI.function, SuppType, &s) || + suppression_ctx->Match(AI.file, SuppType, &s); +} + #endif // CAN_SANITIZE_UB diff --git a/src/compiler-rt/lib/ubsan/ubsan_diag.h b/src/compiler-rt/lib/ubsan/ubsan_diag.h index 2aa62eb743..3edb67a03c 100644 --- a/src/compiler-rt/lib/ubsan/ubsan_diag.h +++ b/src/compiler-rt/lib/ubsan/ubsan_diag.h @@ -211,23 +211,25 @@ public: }; struct ReportOptions { - /// If DieAfterReport is specified, UBSan will terminate the program after the - /// report is printed. - bool DieAfterReport; + // If FromUnrecoverableHandler is specified, UBSan runtime handler is not + // expected to return. + bool FromUnrecoverableHandler; /// pc/bp are used to unwind the stack trace. uptr pc; uptr bp; }; enum class ErrorType { -#define UBSAN_CHECK(Name, SummaryKind, FlagName) Name, +#define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) Name, #include "ubsan_checks.inc" #undef UBSAN_CHECK }; -#define GET_REPORT_OPTIONS(die_after_report) \ +bool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET); + +#define GET_REPORT_OPTIONS(unrecoverable_handler) \ GET_CALLER_PC_BP; \ - ReportOptions Opts = {die_after_report, pc, bp} + ReportOptions Opts = {unrecoverable_handler, pc, bp} /// \brief Instantiate this class before printing diagnostics in the error /// report. This class ensures that reports from different threads and from @@ -238,14 +240,15 @@ class ScopedReport { ErrorType Type; public: - ScopedReport(ReportOptions Opts, Location SummaryLoc, - ErrorType Type = ErrorType::GenericUB); - void setErrorType(ErrorType T) { Type = T; } + ScopedReport(ReportOptions Opts, Location SummaryLoc, ErrorType Type); ~ScopedReport(); }; void InitializeSuppressions(); bool IsVptrCheckSuppressed(const char *TypeName); +// Sometimes UBSan runtime can know filename from handlers arguments, even if +// debug info is missing. +bool IsPCSuppressed(ErrorType ET, uptr PC, const char *Filename); } // namespace __ubsan diff --git a/src/compiler-rt/lib/ubsan/ubsan_handlers.cc b/src/compiler-rt/lib/ubsan/ubsan_handlers.cc index ec6b54e437..5d82e9afcd 100644 --- a/src/compiler-rt/lib/ubsan/ubsan_handlers.cc +++ b/src/compiler-rt/lib/ubsan/ubsan_handlers.cc @@ -21,17 +21,20 @@ using namespace __sanitizer; using namespace __ubsan; -static bool ignoreReport(SourceLocation SLoc, ReportOptions Opts) { - // If source location is already acquired, we don't need to print an error - // report for the second time. However, if we're in an unrecoverable handler, - // it's possible that location was required by concurrently running thread. - // In this case, we should continue the execution to ensure that any of - // threads will grab the report mutex and print the report before - // crashing the program. - return SLoc.isDisabled() && !Opts.DieAfterReport; +namespace __ubsan { +bool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET) { + // We are not allowed to skip error report: if we are in unrecoverable + // handler, we have to terminate the program right now, and therefore + // have to print some diagnostic. + // + // Even if source location is disabled, it doesn't mean that we have + // already report an error to the user: some concurrently running + // thread could have acquired it, but not yet printed the report. + if (Opts.FromUnrecoverableHandler) + return false; + return SLoc.isDisabled() || IsPCSuppressed(ET, Opts.pc, SLoc.getFilename()); } -namespace __ubsan { const char *TypeCheckKinds[] = { "load of", "store to", "reference binding to", "member access within", "member call on", "constructor call on", "downcast of", "downcast of", @@ -41,8 +44,18 @@ const char *TypeCheckKinds[] = { static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer, ReportOptions Opts) { Location Loc = Data->Loc.acquire(); - // Use the SourceLocation from Data to track deduplication, even if 'invalid' - if (ignoreReport(Loc.getSourceLocation(), Opts)) + + ErrorType ET; + if (!Pointer) + ET = ErrorType::NullPointerUse; + else if (Data->Alignment && (Pointer & (Data->Alignment - 1))) + ET = ErrorType::MisalignedPointerUse; + else + ET = ErrorType::InsufficientObjectSize; + + // Use the SourceLocation from Data to track deduplication, even if it's + // invalid. + if (ignoreReport(Loc.getSourceLocation(), Opts, ET)) return; SymbolizedStackHolder FallbackLoc; @@ -51,24 +64,28 @@ static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer, Loc = FallbackLoc; } - ScopedReport R(Opts, Loc); + ScopedReport R(Opts, Loc, ET); - if (!Pointer) { - R.setErrorType(ErrorType::NullPointerUse); + switch (ET) { + case ErrorType::NullPointerUse: Diag(Loc, DL_Error, "%0 null pointer of type %1") - << TypeCheckKinds[Data->TypeCheckKind] << Data->Type; - } else if (Data->Alignment && (Pointer & (Data->Alignment - 1))) { - R.setErrorType(ErrorType::MisalignedPointerUse); + << TypeCheckKinds[Data->TypeCheckKind] << Data->Type; + break; + case ErrorType::MisalignedPointerUse: Diag(Loc, DL_Error, "%0 misaligned address %1 for type %3, " "which requires %2 byte alignment") - << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer - << Data->Alignment << Data->Type; - } else { - R.setErrorType(ErrorType::InsufficientObjectSize); + << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer + << Data->Alignment << Data->Type; + break; + case ErrorType::InsufficientObjectSize: Diag(Loc, DL_Error, "%0 address %1 with insufficient space " "for an object of type %2") - << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type; + << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Data->Type; + break; + default: + UNREACHABLE("unexpected error type!"); } + if (Pointer) Diag(Pointer, DL_Note, "pointer points here"); } @@ -91,12 +108,14 @@ static void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS, const char *Operator, T RHS, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); - if (ignoreReport(Loc, Opts)) + bool IsSigned = Data->Type.isSignedIntegerTy(); + ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow + : ErrorType::UnsignedIntegerOverflow; + + if (ignoreReport(Loc, Opts, ET)) return; - bool IsSigned = Data->Type.isSignedIntegerTy(); - ScopedReport R(Opts, Loc, IsSigned ? ErrorType::SignedIntegerOverflow - : ErrorType::UnsignedIntegerOverflow); + ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "%0 integer overflow: " "%1 %2 %3 cannot be represented in type %4") @@ -104,12 +123,13 @@ static void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS, << Value(Data->Type, LHS) << Operator << RHS << Data->Type; } -#define UBSAN_OVERFLOW_HANDLER(handler_name, op, abort) \ +#define UBSAN_OVERFLOW_HANDLER(handler_name, op, unrecoverable) \ void __ubsan::handler_name(OverflowData *Data, ValueHandle LHS, \ ValueHandle RHS) { \ - GET_REPORT_OPTIONS(abort); \ + GET_REPORT_OPTIONS(unrecoverable); \ handleIntegerOverflowImpl(Data, LHS, op, Value(Data->Type, RHS), Opts); \ - if (abort) Die(); \ + if (unrecoverable) \ + Die(); \ } UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow, "+", false) @@ -122,12 +142,14 @@ UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow_abort, "*", true) static void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); - if (ignoreReport(Loc, Opts)) + bool IsSigned = Data->Type.isSignedIntegerTy(); + ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow + : ErrorType::UnsignedIntegerOverflow; + + if (ignoreReport(Loc, Opts, ET)) return; - bool IsSigned = Data->Type.isSignedIntegerTy(); - ScopedReport R(Opts, Loc, IsSigned ? ErrorType::SignedIntegerOverflow - : ErrorType::UnsignedIntegerOverflow); + ScopedReport R(Opts, Loc, ET); if (IsSigned) Diag(Loc, DL_Error, @@ -154,22 +176,30 @@ void __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data, static void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS, ValueHandle RHS, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); - if (ignoreReport(Loc, Opts)) + Value LHSVal(Data->Type, LHS); + Value RHSVal(Data->Type, RHS); + + ErrorType ET; + if (RHSVal.isMinusOne()) + ET = ErrorType::SignedIntegerOverflow; + else if (Data->Type.isIntegerTy()) + ET = ErrorType::IntegerDivideByZero; + else + ET = ErrorType::FloatDivideByZero; + + if (ignoreReport(Loc, Opts, ET)) return; - ScopedReport R(Opts, Loc); + ScopedReport R(Opts, Loc, ET); - Value LHSVal(Data->Type, LHS); - Value RHSVal(Data->Type, RHS); - if (RHSVal.isMinusOne()) { - R.setErrorType(ErrorType::SignedIntegerOverflow); - Diag(Loc, DL_Error, - "division of %0 by -1 cannot be represented in type %1") - << LHSVal << Data->Type; - } else { - R.setErrorType(Data->Type.isIntegerTy() ? ErrorType::IntegerDivideByZero - : ErrorType::FloatDivideByZero); + switch (ET) { + case ErrorType::SignedIntegerOverflow: + Diag(Loc, DL_Error, "division of %0 by -1 cannot be represented in type %1") + << LHSVal << Data->Type; + break; + default: Diag(Loc, DL_Error, "division by zero"); + break; } } @@ -190,29 +220,34 @@ static void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data, ValueHandle LHS, ValueHandle RHS, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); - if (ignoreReport(Loc, Opts)) + Value LHSVal(Data->LHSType, LHS); + Value RHSVal(Data->RHSType, RHS); + + ErrorType ET; + if (RHSVal.isNegative() || + RHSVal.getPositiveIntValue() >= Data->LHSType.getIntegerBitWidth()) + ET = ErrorType::InvalidShiftExponent; + else + ET = ErrorType::InvalidShiftBase; + + if (ignoreReport(Loc, Opts, ET)) return; - ScopedReport R(Opts, Loc); + ScopedReport R(Opts, Loc, ET); - Value LHSVal(Data->LHSType, LHS); - Value RHSVal(Data->RHSType, RHS); - if (RHSVal.isNegative()) { - R.setErrorType(ErrorType::InvalidShiftExponent); - Diag(Loc, DL_Error, "shift exponent %0 is negative") << RHSVal; - } else if (RHSVal.getPositiveIntValue() >= - Data->LHSType.getIntegerBitWidth()) { - R.setErrorType(ErrorType::InvalidShiftExponent); - Diag(Loc, DL_Error, "shift exponent %0 is too large for %1-bit type %2") - << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType; - } else if (LHSVal.isNegative()) { - R.setErrorType(ErrorType::InvalidShiftBase); - Diag(Loc, DL_Error, "left shift of negative value %0") << LHSVal; + if (ET == ErrorType::InvalidShiftExponent) { + if (RHSVal.isNegative()) + Diag(Loc, DL_Error, "shift exponent %0 is negative") << RHSVal; + else + Diag(Loc, DL_Error, "shift exponent %0 is too large for %1-bit type %2") + << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType; } else { - R.setErrorType(ErrorType::InvalidShiftBase); - Diag(Loc, DL_Error, - "left shift of %0 by %1 places cannot be represented in type %2") - << LHSVal << RHSVal << Data->LHSType; + if (LHSVal.isNegative()) + Diag(Loc, DL_Error, "left shift of negative value %0") << LHSVal; + else + Diag(Loc, DL_Error, + "left shift of %0 by %1 places cannot be represented in type %2") + << LHSVal << RHSVal << Data->LHSType; } } @@ -234,10 +269,12 @@ void __ubsan::__ubsan_handle_shift_out_of_bounds_abort( static void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); - if (ignoreReport(Loc, Opts)) + ErrorType ET = ErrorType::OutOfBoundsIndex; + + if (ignoreReport(Loc, Opts, ET)) return; - ScopedReport R(Opts, Loc, ErrorType::OutOfBoundsIndex); + ScopedReport R(Opts, Loc, ET); Value IndexVal(Data->IndexType, Index); Diag(Loc, DL_Error, "index %0 out of bounds for type %1") @@ -284,10 +321,12 @@ void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) { static void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); - if (ignoreReport(Loc, Opts)) + ErrorType ET = ErrorType::NonPositiveVLAIndex; + + if (ignoreReport(Loc, Opts, ET)) return; - ScopedReport R(Opts, Loc, ErrorType::NonPositiveVLAIndex); + ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "variable length array bound evaluates to " "non-positive value %0") @@ -329,6 +368,7 @@ static void handleFloatCastOverflow(void *DataPtr, ValueHandle From, SymbolizedStackHolder CallerLoc; Location Loc; const TypeDescriptor *FromType, *ToType; + ErrorType ET = ErrorType::FloatCastOverflow; if (looksLikeFloatCastOverflowDataV1(DataPtr)) { auto Data = reinterpret_cast(DataPtr); @@ -339,14 +379,14 @@ static void handleFloatCastOverflow(void *DataPtr, ValueHandle From, } else { auto Data = reinterpret_cast(DataPtr); SourceLocation SLoc = Data->Loc.acquire(); - if (ignoreReport(SLoc, Opts)) + if (ignoreReport(SLoc, Opts, ET)) return; Loc = SLoc; FromType = &Data->FromType; ToType = &Data->ToType; } - ScopedReport R(Opts, Loc, ErrorType::FloatCastOverflow); + ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "value %0 is outside the range of representable values of type %2") @@ -367,14 +407,16 @@ void __ubsan::__ubsan_handle_float_cast_overflow_abort(void *Data, static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); - if (ignoreReport(Loc, Opts)) - return; - // This check could be more precise if we used different handlers for // -fsanitize=bool and -fsanitize=enum. bool IsBool = (0 == internal_strcmp(Data->Type.getTypeName(), "'bool'")); - ScopedReport R(Opts, Loc, IsBool ? ErrorType::InvalidBoolLoad - : ErrorType::InvalidEnumLoad); + ErrorType ET = + IsBool ? ErrorType::InvalidBoolLoad : ErrorType::InvalidEnumLoad; + + if (ignoreReport(Loc, Opts, ET)) + return; + + ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "load of value %0, which is not a valid value for type %1") @@ -397,10 +439,12 @@ static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data, ValueHandle Function, ReportOptions Opts) { SourceLocation CallLoc = Data->Loc.acquire(); - if (ignoreReport(CallLoc, Opts)) + ErrorType ET = ErrorType::FunctionTypeMismatch; + + if (ignoreReport(CallLoc, Opts, ET)) return; - ScopedReport R(Opts, CallLoc, ErrorType::FunctionTypeMismatch); + ScopedReport R(Opts, CallLoc, ET); SymbolizedStackHolder FLoc(getSymbolizedLocation(Function)); const char *FName = FLoc.get()->info.function; @@ -429,10 +473,12 @@ void __ubsan::__ubsan_handle_function_type_mismatch_abort( static void handleNonNullReturn(NonNullReturnData *Data, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); - if (ignoreReport(Loc, Opts)) + ErrorType ET = ErrorType::InvalidNullReturn; + + if (ignoreReport(Loc, Opts, ET)) return; - ScopedReport R(Opts, Loc, ErrorType::InvalidNullReturn); + ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "null pointer returned from function declared to never " "return null"); @@ -453,10 +499,12 @@ void __ubsan::__ubsan_handle_nonnull_return_abort(NonNullReturnData *Data) { static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); - if (ignoreReport(Loc, Opts)) + ErrorType ET = ErrorType::InvalidNullArgument; + + if (ignoreReport(Loc, Opts, ET)) return; - ScopedReport R(Opts, Loc, ErrorType::InvalidNullArgument); + ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "null pointer passed as argument %0, which is declared to " "never be null") << Data->ArgIndex; @@ -478,10 +526,12 @@ void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) { static void handleCFIBadIcall(CFIBadIcallData *Data, ValueHandle Function, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); - if (ignoreReport(Loc, Opts)) + ErrorType ET = ErrorType::CFIBadType; + + if (ignoreReport(Loc, Opts, ET)) return; - ScopedReport R(Opts, Loc); + ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during " "indirect function call") diff --git a/src/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc b/src/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc index 674e406c58..3e81be6716 100644 --- a/src/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc +++ b/src/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc @@ -29,23 +29,25 @@ namespace __ubsan { extern const char *TypeCheckKinds[]; } -static void HandleDynamicTypeCacheMiss( +// Returns true if UBSan has printed an error report. +static bool HandleDynamicTypeCacheMiss( DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash, ReportOptions Opts) { if (checkDynamicType((void*)Pointer, Data->TypeInfo, Hash)) // Just a cache miss. The type matches after all. - return; + return false; // Check if error report should be suppressed. DynamicTypeInfo DTI = getDynamicTypeInfoFromObject((void*)Pointer); if (DTI.isValid() && IsVptrCheckSuppressed(DTI.getMostDerivedTypeName())) - return; + return false; SourceLocation Loc = Data->Loc.acquire(); - if (Loc.isDisabled()) - return; + ErrorType ET = ErrorType::DynamicTypeMismatch; + if (ignoreReport(Loc, Opts, ET)) + return false; - ScopedReport R(Opts, Loc, ErrorType::DynamicTypeMismatch); + ScopedReport R(Opts, Loc, ET); Diag(Loc, DL_Error, "%0 address %1 which does not point to an object of type %2") @@ -69,6 +71,7 @@ static void HandleDynamicTypeCacheMiss( << TypeName(DTI.getSubobjectTypeName()) << Range(Pointer, Pointer + sizeof(uptr), "vptr for %2 base class of %1"); + return true; } void __ubsan::__ubsan_handle_dynamic_type_cache_miss( @@ -78,14 +81,21 @@ void __ubsan::__ubsan_handle_dynamic_type_cache_miss( } void __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort( DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) { - GET_REPORT_OPTIONS(true); - HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts); + // Note: -fsanitize=vptr is always recoverable. + GET_REPORT_OPTIONS(false); + if (HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts)) + Die(); } static void HandleCFIBadType(CFIBadTypeData *Data, ValueHandle Vtable, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); - ScopedReport R(Opts, Loc, ErrorType::CFIBadType); + ErrorType ET = ErrorType::CFIBadType; + + if (ignoreReport(Loc, Opts, ET)) + return; + + ScopedReport R(Opts, Loc, ET); DynamicTypeInfo DTI = getDynamicTypeInfoFromVtable((void*)Vtable); static const char *TypeCheckKinds[] = { @@ -117,6 +127,7 @@ void __ubsan::__ubsan_handle_cfi_bad_type_abort(CFIBadTypeData *Data, ValueHandle Vtable) { GET_REPORT_OPTIONS(true); HandleCFIBadType(Data, Vtable, Opts); + Die(); } #endif // CAN_SANITIZE_UB diff --git a/src/compiler-rt/make/config.mk b/src/compiler-rt/make/config.mk index 0998aca0de..094fd160f9 100644 --- a/src/compiler-rt/make/config.mk +++ b/src/compiler-rt/make/config.mk @@ -44,6 +44,6 @@ endif ### # Common compiler options COMMON_INCLUDES=-I${ProjSrcRoot}/lib -I${ProjSrcRoot}/include -COMMON_CXXFLAGS=-std=c++11 -fno-exceptions -funwind-tables $(COMMON_INCLUDES) -COMMON_CFLAGS=$(COMMON_INCLUDES) +COMMON_CXXFLAGS=-std=c++11 -fno-exceptions -fPIC -funwind-tables $(COMMON_INCLUDES) +COMMON_CFLAGS=-fPIC $(COMMON_INCLUDES) COMMON_ASMFLAGS=$(COMMON_INCLUDES) diff --git a/src/compiler-rt/make/platform/clang_darwin.mk b/src/compiler-rt/make/platform/clang_darwin.mk new file mode 100644 index 0000000000..9944481d8b --- /dev/null +++ b/src/compiler-rt/make/platform/clang_darwin.mk @@ -0,0 +1,567 @@ +# These are the functions which clang needs when it is targeting a previous +# version of the OS. The issue is that the backend may use functions which were +# not present in the libgcc that shipped on the platform. In such cases, we link +# with a version of the library which contains private_extern definitions of all +# the extra functions which might be referenced. + +Description := Static runtime libraries for clang/Darwin. + +# A function that ensures we don't try to build for architectures and SDKs +# that we don't have working toolchains for. Arguments: +# (1): List of architectures +# (2): Library name +# (3): SDK path +# The result is a possibly empty subset of the architectures from argument 1. +CheckArches = \ + $(shell \ + result=""; \ + if [ "X$(3)" != X ]; then \ + for arch in $(1); do \ + if $(LD) -v 2>&1 | grep "configured to support" \ + | tr ' ' '\n' | grep "^$$arch$$" >/dev/null 2>/dev/null; then \ + if $(CC) -arch $$arch \ + -integrated-as \ + $(ProjSrcRoot)/make/platform/clang_darwin_test_input.c \ + -isysroot $(3) \ + -o /dev/null > /dev/null 2> /dev/null; then \ + result="$$result$$arch "; \ + else \ + printf 1>&2 \ + "warning: clang_darwin.mk: dropping arch '$$arch' from lib '$(2)'"; \ + printf 1>&2 " (clang or system libraries do not support it)\n"; \ + fi; \ + else \ + printf 1>&2 \ + "warning: clang_darwin.mk: dropping arch '$$arch' from lib '$(2)'";\ + printf 1>&2 " (ld does not support it)\n"; \ + fi; \ + done; \ + fi; \ + echo $$result) + +XCRun = \ + $(shell \ + result=`xcrun -find $(1) 2> /dev/null`; \ + if [ "$$?" != "0" ]; then result=$(1); fi; \ + echo $$result) +# Prefer building with the internal SDKs. +XCRunSdkPath = \ + $(shell \ + result=`xcrun --sdk $(1).internal --show-sdk-path 2> /dev/null`; \ + if [ "$$?" != "0" ]; then \ + result=`xcrun --sdk $(1) --show-sdk-path 2> /dev/null`; \ + if [ "$$?" != "0" ]; then result=""; fi; \ + fi; \ + echo $$result) +### + +CC := $(call XCRun,clang) +LD := $(shell $(CC) -print-prog-name=ld) +AR := $(call XCRun,ar) +RANLIB := $(call XCRun,ranlib) +STRIP := $(call XCRun,strip) +LIPO := $(call XCRun,lipo) +DSYMUTIL := $(call XCRun,dsymutil) + +OSX_SDK := $(call XCRunSdkPath,macosx) +IOS_SDK := $(call XCRunSdkPath,iphoneos) +IOSSIM_SDK := $(call XCRunSdkPath,iphonesimulator) + +Configs := +UniversalArchs := + +# Configuration solely for providing access to an eprintf symbol, which may +# still be referenced from Darwin system headers. This symbol is only ever +# needed on i386. +Configs += eprintf +UniversalArchs.eprintf := $(call CheckArches,i386,eprintf,$(OSX_SDK)) + +# Configuration for targeting 10.4. We need a few functions missing from +# libgcc_s.10.4.dylib. We only build x86 slices since clang doesn't really +# support targeting PowerPC. +Configs += 10.4 +UniversalArchs.10.4 := $(call CheckArches,i386 x86_64,10.4,$(OSX_SDK)) + +# Configuration for targeting iOS for a couple of functions that didn't +# make it into libSystem. +Configs += ios +UniversalArchs.ios := $(call CheckArches,i386 x86_64,ios,$(IOSSIM_SDK)) +UniversalArchs.ios += $(call CheckArches,armv7 arm64,ios,$(IOS_SDK)) + +# Configuration for targeting OSX. These functions may not be in libSystem +# so we should provide our own. +Configs += osx +UniversalArchs.osx := $(call CheckArches,i386 x86_64 x86_64h,osx,$(OSX_SDK)) + +# Configuration for use with kernel/kexts. +Configs += cc_kext +UniversalArchs.cc_kext := $(call CheckArches,i386 x86_64 x86_64h,cc_kext,$(OSX_SDK)) + +# Configuration for use with iOS kernel/kexts +Configs += cc_kext_ios +UniversalArchs.cc_kext_ios += $(call CheckArches,armv7,cc_kext_ios,$(IOS_SDK)) + +# Configurations which define the profiling support functions. +Configs += profile_osx +UniversalArchs.profile_osx := $(call CheckArches,i386 x86_64 x86_64h,profile_osx,$(OSX_SDK)) +Configs += profile_ios +UniversalArchs.profile_ios := $(call CheckArches,i386 x86_64,profile_ios,$(IOSSIM_SDK)) +UniversalArchs.profile_ios += $(call CheckArches,armv7 arm64,profile_ios,$(IOS_SDK)) + +# Configurations which define the ASAN support functions. +Configs += asan_osx_dynamic +UniversalArchs.asan_osx_dynamic := $(call CheckArches,i386 x86_64 x86_64h,asan_osx_dynamic,$(OSX_SDK)) + +Configs += asan_iossim_dynamic +UniversalArchs.asan_iossim_dynamic := $(call CheckArches,i386 x86_64,asan_iossim_dynamic,$(IOSSIM_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 +# build the libraries themselves so that Clang can find them where it expects +# them, even though they might not have an expected slice. +ifneq ($(shell test -x /usr/bin/sw_vers && sw_vers -productVersion | grep 10.6),) +UniversalArchs.ios := $(filter-out armv7, $(UniversalArchs.ios)) +UniversalArchs.cc_kext_ios := $(filter-out armv7, $(UniversalArchs.cc_kext_ios)) +UniversalArchs.profile_ios := $(filter-out armv7, $(UniversalArchs.profile_ios)) +endif + +# If RC_SUPPORTED_ARCHS is defined, treat it as a list of the architectures we +# are intended to support and limit what we try to build to that. +ifneq ($(RC_SUPPORTED_ARCHS),) +$(foreach config,$(Configs),\ + $(call Set,UniversalArchs.$(config),\ + $(filter $(RC_SUPPORTED_ARCHS),$(UniversalArchs.$(config))))) +endif + +# Remove empty configs if we end up dropping all the requested +# archs for a particular config. +$(foreach config,$(Configs),\ + $(if $(strip $(UniversalArchs.$(config))),,\ + $(call Set,Configs,$(filter-out $(config),$(Configs))))) + +### + +# Forcibly strip off any -arch, as that totally breaks our universal support. +override CC := $(subst -arch ,-arch_,$(CC)) +override CC := $(patsubst -arch_%,,$(CC)) + +CFLAGS := -Wall -Werror -O3 -fomit-frame-pointer + +# Always set deployment target arguments for every build, these libraries should +# never depend on the environmental overrides. We simply set them to minimum +# supported deployment target -- nothing in the compiler-rt libraries should +# actually depend on the deployment target. +OSX_DEPLOYMENT_ARGS := -mmacosx-version-min=10.4 +IOS_DEPLOYMENT_ARGS := -mios-version-min=1.0 +IOS6_DEPLOYMENT_ARGS := -mios-version-min=6.0 +IOSSIM_DEPLOYMENT_ARGS := -mios-simulator-version-min=1.0 + +OSX_DEPLOYMENT_ARGS += -isysroot $(OSX_SDK) +IOS_DEPLOYMENT_ARGS += -isysroot $(IOS_SDK) +IOS6_DEPLOYMENT_ARGS += -isysroot $(IOS_SDK) +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) $(SANITIZER_MACOSX_DEPLOYMENT_ARGS) \ + $(SANITIZER_CFLAGS) \ + -DMAC_INTERPOSE_FUNCTIONS=1 \ + -DASAN_DYNAMIC=1 + +CFLAGS.asan_iossim_dynamic := \ + $(CFLAGS) $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS) \ + $(SANITIZER_CFLAGS) \ + -DMAC_INTERPOSE_FUNCTIONS=1 \ + -DASAN_DYNAMIC=1 + +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) +CFLAGS.ios.armv7 := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) +CFLAGS.ios.armv7k := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) +CFLAGS.ios.armv7s := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) +CFLAGS.ios.arm64 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) +CFLAGS.osx.i386 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) +CFLAGS.osx.x86_64 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) +CFLAGS.osx.x86_64h := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) +CFLAGS.cc_kext.i386 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) +CFLAGS.cc_kext.x86_64 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) +CFLAGS.cc_kext.x86_64h := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) +CFLAGS.cc_kext_ios.armv7 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) +CFLAGS.cc_kext_ios.armv7k := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) +CFLAGS.cc_kext_ios.armv7s := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) +CFLAGS.cc_kext_ios.arm64 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) +CFLAGS.profile_osx.i386 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) +CFLAGS.profile_osx.x86_64 := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) +CFLAGS.profile_osx.x86_64h := $(CFLAGS) $(OSX_DEPLOYMENT_ARGS) +CFLAGS.profile_ios.i386 := $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS) +CFLAGS.profile_ios.x86_64 := $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS) +CFLAGS.profile_ios.armv7 := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) +CFLAGS.profile_ios.armv7k := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) +CFLAGS.profile_ios.armv7s := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS) +CFLAGS.profile_ios.arm64 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS) + +SANITIZER_LDFLAGS := -stdlib=libc++ -lc++ -lc++abi + +SHARED_LIBRARY.asan_osx_dynamic := 1 +LDFLAGS.asan_osx_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.asan_osx_dynamic.dylib \ + $(SANITIZER_MACOSX_DEPLOYMENT_ARGS) + +SHARED_LIBRARY.asan_iossim_dynamic := 1 +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) -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) -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 + +ATOMIC_FUNCTIONS := \ + atomic_flag_clear \ + atomic_flag_clear_explicit \ + atomic_flag_test_and_set \ + atomic_flag_test_and_set_explicit \ + atomic_signal_fence \ + atomic_thread_fence + +FP16_FUNCTIONS := \ + extendhfsf2 \ + truncdfhf2 \ + truncsfhf2 + +FUNCTIONS.eprintf := eprintf +FUNCTIONS.10.4 := eprintf floatundidf floatundisf floatundixf + +FUNCTIONS.ios := divmodsi4 udivmodsi4 mulosi4 mulodi4 muloti4 \ + $(ATOMIC_FUNCTIONS) $(FP16_FUNCTIONS) +# On x86, the divmod functions reference divsi. +FUNCTIONS.ios.i386 := $(FUNCTIONS.ios) \ + divsi3 udivsi3 +FUNCTIONS.ios.x86_64 := $(FUNCTIONS.ios.i386) +FUNCTIONS.ios.arm64 := mulsc3 muldc3 divsc3 divdc3 udivti3 umodti3 \ + $(ATOMIC_FUNCTIONS) + +FUNCTIONS.osx := mulosi4 mulodi4 muloti4 $(ATOMIC_FUNCTIONS) $(FP16_FUNCTIONS) + +FUNCTIONS.profile_osx := GCDAProfiling InstrProfiling InstrProfilingBuffer \ + InstrProfilingFile InstrProfilingPlatformDarwin \ + InstrProfilingRuntime InstrProfilingUtil \ + InstrProfilingWriter InstrProfilingValue +FUNCTIONS.profile_ios := $(FUNCTIONS.profile_osx) + +FUNCTIONS.asan_osx_dynamic := $(AsanFunctions) $(AsanCXXFunctions) \ + $(InterceptionFunctions) \ + $(SanitizerCommonFunctions) \ + $(AsanDynamicFunctions) \ + $(UbsanFunctions) $(UbsanCXXFunctions) + +FUNCTIONS.asan_iossim_dynamic := $(AsanFunctions) $(AsanCXXFunctions) \ + $(InterceptionFunctions) \ + $(SanitizerCommonFunctions) \ + $(AsanDynamicFunctions) \ + $(UbsanFunctions) $(UbsanCXXFunctions) + +FUNCTIONS.ubsan_osx_dynamic := $(UbsanFunctions) $(UbsanCXXFunctions) \ + $(SanitizerCommonFunctions) \ + $(UbsanStandaloneFunctions) + +FUNCTIONS.ubsan_iossim_dynamic := $(UbsanFunctions) $(UbsanCXXFunctions) \ + $(SanitizerCommonFunctions) \ + $(UbsanStandaloneFunctions) + +CCKEXT_PROFILE_FUNCTIONS := \ + InstrProfiling \ + InstrProfilingBuffer \ + InstrProfilingPlatformDarwin + +CCKEXT_COMMON_FUNCTIONS := \ + $(CCKEXT_PROFILE_FUNCTIONS) \ + absvdi2 \ + absvsi2 \ + addvdi3 \ + addvsi3 \ + ashldi3 \ + ashrdi3 \ + bswapdi2 \ + bswapsi2 \ + clzdi2 \ + clzsi2 \ + cmpdi2 \ + ctzdi2 \ + ctzsi2 \ + divdc3 \ + divdi3 \ + divsc3 \ + divmodsi4 \ + udivmodsi4 \ + do_global_dtors \ + eprintf \ + extendhfsf2 \ + ffsdi2 \ + fixdfdi \ + fixsfdi \ + fixunsdfdi \ + fixunsdfsi \ + fixunssfdi \ + fixunssfsi \ + floatdidf \ + floatdisf \ + floatundidf \ + floatundisf \ + gcc_bcmp \ + lshrdi3 \ + moddi3 \ + muldc3 \ + muldi3 \ + mulsc3 \ + mulvdi3 \ + mulvsi3 \ + negdi2 \ + negvdi2 \ + negvsi2 \ + paritydi2 \ + paritysi2 \ + popcountdi2 \ + popcountsi2 \ + powidf2 \ + powisf2 \ + subvdi3 \ + subvsi3 \ + truncdfhf2 \ + truncsfhf2 \ + ucmpdi2 \ + udiv_w_sdiv \ + udivdi3 \ + udivmoddi4 \ + umoddi3 + +CCKEXT_ARM_FUNCTIONS := $(CCKEXT_COMMON_FUNCTIONS) \ + adddf3 \ + addsf3 \ + aeabi_cdcmpeq \ + aeabi_cdrcmple \ + aeabi_cfcmpeq \ + aeabi_cfrcmple \ + aeabi_dcmpeq \ + aeabi_dcmpge \ + aeabi_dcmpgt \ + aeabi_dcmple \ + aeabi_dcmplt \ + aeabi_drsub \ + aeabi_fcmpeq \ + aeabi_fcmpge \ + aeabi_fcmpgt \ + aeabi_fcmple \ + aeabi_fcmplt \ + aeabi_frsub \ + aeabi_idivmod \ + aeabi_uidivmod \ + cmpdf2 \ + cmpsf2 \ + div0 \ + divdf3 \ + divsf3 \ + divsi3 \ + extendsfdf2 \ + ffssi2 \ + fixdfsi \ + fixsfsi \ + floatsidf \ + floatsisf \ + floatunsidf \ + floatunsisf \ + comparedf2 \ + comparesf2 \ + modsi3 \ + muldf3 \ + mulsf3 \ + mulodi4 \ + negdf2 \ + negsf2 \ + subdf3 \ + subsf3 \ + switch16 \ + switch32 \ + switch8 \ + switchu8 \ + truncdfsf2 \ + udivsi3 \ + umodsi3 \ + unorddf2 \ + unordsf2 + +CCKEXT_ARMVFP_FUNCTIONS := $(CCKEXT_ARM_FUNCTIONS) \ + adddf3vfp \ + addsf3vfp \ + divdf3vfp \ + divsf3vfp \ + eqdf2vfp \ + eqsf2vfp \ + extendsfdf2vfp \ + fixdfsivfp \ + fixsfsivfp \ + fixunsdfsivfp \ + fixunssfsivfp \ + floatsidfvfp \ + floatsisfvfp \ + floatunssidfvfp \ + floatunssisfvfp \ + gedf2vfp \ + gesf2vfp \ + gtdf2vfp \ + gtsf2vfp \ + ledf2vfp \ + lesf2vfp \ + ltdf2vfp \ + ltsf2vfp \ + muldf3vfp \ + mulsf3vfp \ + nedf2vfp \ + nesf2vfp \ + subdf3vfp \ + subsf3vfp \ + truncdfsf2vfp \ + unorddf2vfp \ + unordsf2vfp + +CCKEXT_ARM64_FUNCTIONS := \ + $(CCKEXT_PROFILE_FUNCTIONS) \ + divdc3 \ + divsc3 \ + muldc3 \ + mulsc3 \ + udivti3 \ + umodti3 + +FUNCTIONS.cc_kext_ios.armv7 := $(CCKEXT_ARMVFP_FUNCTIONS) +FUNCTIONS.cc_kext_ios.armv7k := $(CCKEXT_ARMVFP_FUNCTIONS) +FUNCTIONS.cc_kext_ios.armv7s := $(CCKEXT_ARMVFP_FUNCTIONS) +FUNCTIONS.cc_kext_ios.arm64 := $(CCKEXT_ARM64_FUNCTIONS) + +CCKEXT_X86_FUNCTIONS := $(CCKEXT_COMMON_FUNCTIONS) \ + divxc3 \ + fixunsxfdi \ + fixunsxfsi \ + fixxfdi \ + floatdixf \ + floatundixf \ + mulxc3 \ + powixf2 + +FUNCTIONS.cc_kext.i386 := $(CCKEXT_X86_FUNCTIONS) \ + ffssi2 \ + i686.get_pc_thunk.eax \ + i686.get_pc_thunk.ebp \ + i686.get_pc_thunk.ebx \ + i686.get_pc_thunk.ecx \ + i686.get_pc_thunk.edi \ + i686.get_pc_thunk.edx \ + i686.get_pc_thunk.esi + +FUNCTIONS.cc_kext.x86_64 := $(CCKEXT_X86_FUNCTIONS) \ + absvti2 \ + addvti3 \ + ashlti3 \ + ashrti3 \ + clzti2 \ + cmpti2 \ + ctzti2 \ + divti3 \ + ffsti2 \ + fixdfti \ + fixsfti \ + fixunsdfti \ + fixunssfti \ + fixunsxfti \ + fixxfti \ + floattidf \ + floattisf \ + floattixf \ + floatuntidf \ + floatuntisf \ + floatuntixf \ + lshrti3 \ + modti3 \ + multi3 \ + mulvti3 \ + negti2 \ + negvti2 \ + parityti2 \ + popcountti2 \ + subvti3 \ + ucmpti2 \ + udivmodti4 \ + udivti3 \ + umodti3 + +FUNCTIONS.cc_kext.x86_64h := $(FUNCTIONS.cc_kext.x86_64) + +# FIXME: Currently, compiler-rt is missing implementations for a number of the +# functions that need to go into libcc_kext.a. Filter them out for now. +CCKEXT_MISSING_FUNCTIONS := \ + cmpdf2 cmpsf2 div0 \ + ffssi2 \ + udiv_w_sdiv unorddf2 unordsf2 bswapdi2 \ + bswapsi2 \ + gcc_bcmp \ + do_global_dtors \ + i686.get_pc_thunk.eax i686.get_pc_thunk.ebp i686.get_pc_thunk.ebx \ + i686.get_pc_thunk.ecx i686.get_pc_thunk.edi i686.get_pc_thunk.edx \ + i686.get_pc_thunk.esi \ + aeabi_cdcmpeq aeabi_cdrcmple aeabi_cfcmpeq aeabi_cfrcmple aeabi_dcmpeq \ + aeabi_dcmpge aeabi_dcmpgt aeabi_dcmple aeabi_dcmplt aeabi_drsub aeabi_fcmpeq \ + aeabi_fcmpge aeabi_fcmpgt aeabi_fcmple aeabi_fcmplt aeabi_frsub aeabi_idivmod \ + aeabi_uidivmod + +FUNCTIONS.cc_kext_ios.armv7 := \ + $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext_ios.armv7)) +FUNCTIONS.cc_kext_ios.armv7k := \ + $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext_ios.armv7k)) +FUNCTIONS.cc_kext_ios.armv7s := \ + $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext_ios.armv7s)) +FUNCTIONS.cc_kext_ios.arm64 := \ + $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext_ios.arm64)) +FUNCTIONS.cc_kext.i386 := \ + $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext.i386)) +FUNCTIONS.cc_kext.x86_64 := \ + $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext.x86_64)) +FUNCTIONS.cc_kext.x86_64h := \ + $(filter-out $(CCKEXT_MISSING_FUNCTIONS),$(FUNCTIONS.cc_kext.x86_64h)) + +KERNEL_USE.cc_kext := 1 +KERNEL_USE.cc_kext_ios := 1 + +VISIBILITY_HIDDEN := 1 + +SHARED_LIBRARY_SUFFIX := dylib diff --git a/src/compiler-rt/make/platform/clang_darwin_test_input.c b/src/compiler-rt/make/platform/clang_darwin_test_input.c new file mode 100644 index 0000000000..b406a28a63 --- /dev/null +++ b/src/compiler-rt/make/platform/clang_darwin_test_input.c @@ -0,0 +1,15 @@ +/* Include the headers we use in int_lib.h, to verify that they work. */ + +#include +#include +#include +#include +#include + +// Force us to link at least one symbol in a system library +// to detect systems where we don't have those for a given +// architecture. +int main(int argc, const char **argv) { + int x; + memcpy(&x,&argc,sizeof(int)); +} diff --git a/src/compiler-rt/make/platform/clang_linux.mk b/src/compiler-rt/make/platform/clang_linux.mk new file mode 100644 index 0000000000..bf5ee4a928 --- /dev/null +++ b/src/compiler-rt/make/platform/clang_linux.mk @@ -0,0 +1,91 @@ +Description := Static runtime libraries for clang/Linux. + +### + +CC := clang +Arch := unknown +Configs := + +# We don't currently have any general purpose way to target architectures other +# than the compiler defaults (because there is no generalized way to invoke +# cross compilers). For now, we just find the target architecture of the +# compiler and only define configurations we know that compiler can generate. +CompilerTargetTriple := $(shell \ + LANG=C $(CC) -v 2>&1 | grep 'Target:' | cut -d' ' -f2) +ifeq ($(CompilerTargetTriple),) +$(error "unable to infer compiler target triple for $(CC)") +endif + +# Only define configs if we detected a linux target. +ifneq ($(findstring -linux-,$(CompilerTargetTriple)),) + +# Define configs only if arch in triple is i386 or x86_64 +CompilerTargetArch := $(firstword $(subst -, ,$(CompilerTargetTriple))) +ifeq ($(call contains,i386 x86_64,$(CompilerTargetArch)),true) + +# TryCompile compiler source flags +# Returns exit code of running a compiler invocation. +TryCompile = \ + $(shell \ + cflags=""; \ + for flag in $(3); do \ + cflags="$$cflags $$flag"; \ + done; \ + $(1) $$cflags $(2) -o /dev/null > /dev/null 2> /dev/null ; \ + echo $$?) + +test_source = $(ProjSrcRoot)/make/platform/clang_linux_test_input.c +ifeq ($(CompilerTargetArch),i386) + SupportedArches := i386 + ifeq ($(call TryCompile,$(CC),$(test_source),-m64),0) + SupportedArches += x86_64 + endif +else + SupportedArches := x86_64 + ifeq ($(call TryCompile,$(CC),$(test_source),-m32),0) + SupportedArches += i386 + endif +endif + +# Build runtime libraries for i386. +ifeq ($(call contains,$(SupportedArches),i386),true) +Configs += builtins-i386 profile-i386 +Arch.builtins-i386 := i386 +Arch.profile-i386 := i386 +endif + +# Build runtime libraries for x86_64. +ifeq ($(call contains,$(SupportedArches),x86_64),true) +Configs += builtins-x86_64 profile-x86_64 +Arch.builtins-x86_64 := x86_64 +Arch.profile-x86_64 := x86_64 +endif + +endif + +endif + +### + +CFLAGS := -Wall -Werror -O3 -fomit-frame-pointer + +CFLAGS.builtins-i386 := $(CFLAGS) -m32 +CFLAGS.builtins-x86_64 := $(CFLAGS) -m64 +CFLAGS.profile-i386 := $(CFLAGS) -m32 +CFLAGS.profile-x86_64 := $(CFLAGS) -m64 + +FUNCTIONS.builtins-i386 := $(CommonFunctions) $(ArchFunctions.i386) +FUNCTIONS.builtins-x86_64 := $(CommonFunctions) $(ArchFunctions.x86_64) +FUNCTIONS.profile-i386 := GCDAProfiling InstrProfiling InstrProfilingBuffer \ + InstrProfilingFile InstrProfilingPlatformOther \ + InstrProfilingRuntime InstrProfilingUtil \ + InstrProfilingWriter InstrProfilingValue +FUNCTIONS.profile-x86_64 := $(FUNCTIONS.profile-i386) + +# Always use optimized variants. +OPTIMIZED := 1 + +# We don't need to use visibility hidden on Linux. +VISIBILITY_HIDDEN := 0 + +SHARED_LIBRARY_SUFFIX := so diff --git a/src/compiler-rt/make/platform/clang_linux_test_input.c b/src/compiler-rt/make/platform/clang_linux_test_input.c new file mode 100644 index 0000000000..e65ce9860a --- /dev/null +++ b/src/compiler-rt/make/platform/clang_linux_test_input.c @@ -0,0 +1,4 @@ +// This file is used to check if we can produce working executables +// for i386 and x86_64 archs on Linux. +#include +int main(){} diff --git a/src/compiler-rt/make/platform/clang_macho_embedded.mk b/src/compiler-rt/make/platform/clang_macho_embedded.mk new file mode 100644 index 0000000000..d7870d491f --- /dev/null +++ b/src/compiler-rt/make/platform/clang_macho_embedded.mk @@ -0,0 +1,297 @@ +# These are the functions which clang needs when it is targeting a previous +# version of the OS. The issue is that the backend may use functions which were +# not present in the libgcc that shipped on the platform. In such cases, we link +# with a version of the library which contains private_extern definitions of all +# the extra functions which might be referenced. + +Description := Static runtime libraries for embedded clang/Darwin + +# A function that ensures we don't try to build for architectures that we +# don't have working toolchains for. +CheckArches = \ + $(shell \ + result=""; \ + for arch in $(1); do \ + if $(CC) -arch $$arch -c \ + -integrated-as \ + $(ProjSrcRoot)/make/platform/clang_macho_embedded_test_input.c \ + -o /dev/null > /dev/null 2> /dev/null; then \ + result="$$result$$arch "; \ + else \ + printf 1>&2 \ + "warning: clang_macho_embedded.mk: dropping arch '$$arch' from lib '$(2)'\n"; \ + fi; \ + done; \ + echo $$result) + +XCRun = \ + $(shell \ + result=`xcrun -find $(1) 2> /dev/null`; \ + if [ "$$?" != "0" ]; then result=$(1); fi; \ + echo $$result) + +### + +CC := $(call XCRun,clang) +AR := $(call XCRun,ar) +RANLIB := $(call XCRun,ranlib) +STRIP := $(call XCRun,strip) +LIPO := $(call XCRun,lipo) +DSYMUTIL := $(call XCRun,dsymutil) + +Configs := +UniversalArchs := + +# Soft-float version of the runtime. No floating-point instructions will be used +# and the ABI (out of necessity) passes floating values in normal registers: +# non-VFP variant of the AAPCS. +UniversalArchs.soft_static := $(call CheckArches,armv6m armv7m armv7em armv7,soft_static) +Configs += $(if $(UniversalArchs.soft_static),soft_static) + +# Hard-float version of the runtime. On ARM VFP instructions and registers are +# allowed, and floating point values get passed in them. VFP variant of the +# AAPCS. +UniversalArchs.hard_static := $(call CheckArches,armv7em armv7 i386 x86_64,hard_static) +Configs += $(if $(UniversalArchs.hard_static),hard_static) + +UniversalArchs.soft_pic := $(call CheckArches,armv6m armv7m armv7em armv7,soft_pic) +Configs += $(if $(UniversalArchs.soft_pic),soft_pic) + +UniversalArchs.hard_pic := $(call CheckArches,armv7em armv7 i386 x86_64,hard_pic) +Configs += $(if $(UniversalArchs.hard_pic),hard_pic) + +CFLAGS := -Wall -Werror -Oz -fomit-frame-pointer -ffreestanding + +PIC_CFLAGS := -fPIC +STATIC_CFLAGS := -static + +CFLAGS_SOFT := -mfloat-abi=soft +CFLAGS_HARD := -mfloat-abi=hard + +CFLAGS_ARMV7 := -target thumbv7-apple-darwin-eabi +CFLAGS_I386 := -march=pentium + +CFLAGS.soft_static := $(CFLAGS) $(STATIC_CFLAGS) $(CFLAGS_SOFT) +CFLAGS.hard_static := $(CFLAGS) $(STATIC_CFLAGS) $(CFLAGS_HARD) +CFLAGS.soft_pic := $(CFLAGS) $(PIC_CFLAGS) $(CFLAGS_SOFT) +CFLAGS.hard_pic := $(CFLAGS) $(PIC_CFLAGS) $(CFLAGS_HARD) + +CFLAGS.soft_static.armv7 := $(CFLAGS.soft_static) $(CFLAGS_ARMV7) +CFLAGS.hard_static.armv7 := $(CFLAGS.hard_static) $(CFLAGS_ARMV7) +CFLAGS.soft_pic.armv7 := $(CFLAGS.soft_pic) $(CFLAGS_ARMV7) +CFLAGS.hard_pic.armv7 := $(CFLAGS.hard_pic) $(CFLAGS_ARMV7) + +# x86 platforms ignore -mfloat-abi options and complain about doing so. Despite +# this they're hard-float. +CFLAGS.hard_static.i386 := $(CFLAGS) $(STATIC_CFLAGS) $(CFLAGS_I386) +CFLAGS.hard_pic.i386 := $(CFLAGS) $(PIC_CFLAGS) $(CFLAGS_I386) +CFLAGS.hard_static.x86_64 := $(CFLAGS) $(STATIC_CFLAGS) +CFLAGS.hard_pic.x86_64 := $(CFLAGS) $(PIC_CFLAGS) + +# Functions not wanted: +# + eprintf is obsolete anyway +# + *vfp: designed for Thumb1 CPUs with VFPv2 + +COMMON_FUNCTIONS := \ + absvdi2 \ + absvsi2 \ + addvdi3 \ + addvsi3 \ + ashldi3 \ + ashrdi3 \ + bswapdi2 \ + bswapsi2 \ + clzdi2 \ + clzsi2 \ + cmpdi2 \ + ctzdi2 \ + ctzsi2 \ + divdc3 \ + divdi3 \ + divsc3 \ + divmodsi4 \ + udivmodsi4 \ + do_global_dtors \ + ffsdi2 \ + fixdfdi \ + fixsfdi \ + fixunsdfdi \ + fixunsdfsi \ + fixunssfdi \ + fixunssfsi \ + floatdidf \ + floatdisf \ + floatundidf \ + floatundisf \ + gcc_bcmp \ + lshrdi3 \ + moddi3 \ + muldc3 \ + muldi3 \ + mulsc3 \ + mulvdi3 \ + mulvsi3 \ + negdi2 \ + negvdi2 \ + negvsi2 \ + paritydi2 \ + paritysi2 \ + popcountdi2 \ + popcountsi2 \ + powidf2 \ + powisf2 \ + subvdi3 \ + subvsi3 \ + ucmpdi2 \ + udiv_w_sdiv \ + udivdi3 \ + udivmoddi4 \ + umoddi3 \ + adddf3 \ + addsf3 \ + cmpdf2 \ + cmpsf2 \ + div0 \ + divdf3 \ + divsf3 \ + divsi3 \ + extendsfdf2 \ + extendhfsf2 \ + ffssi2 \ + fixdfsi \ + fixsfsi \ + floatsidf \ + floatsisf \ + floatunsidf \ + floatunsisf \ + comparedf2 \ + comparesf2 \ + modsi3 \ + muldf3 \ + mulsf3 \ + negdf2 \ + negsf2 \ + subdf3 \ + subsf3 \ + truncdfhf2 \ + truncdfsf2 \ + truncsfhf2 \ + udivsi3 \ + umodsi3 \ + unorddf2 \ + unordsf2 \ + atomic_flag_clear \ + atomic_flag_clear_explicit \ + atomic_flag_test_and_set \ + atomic_flag_test_and_set_explicit \ + atomic_signal_fence \ + atomic_thread_fence + +ARM_FUNCTIONS := \ + aeabi_cdcmpeq \ + aeabi_cdrcmple \ + aeabi_cfcmpeq \ + aeabi_cfrcmple \ + aeabi_dcmpeq \ + aeabi_dcmpge \ + aeabi_dcmpgt \ + aeabi_dcmple \ + aeabi_dcmplt \ + aeabi_drsub \ + aeabi_fcmpeq \ + aeabi_fcmpge \ + aeabi_fcmpgt \ + aeabi_fcmple \ + aeabi_fcmplt \ + aeabi_frsub \ + aeabi_idivmod \ + aeabi_uidivmod \ + +# ARM Assembly implementation which requires Thumb2 (i.e. won't work on v6M). +THUMB2_FUNCTIONS := \ + switch16 \ + switch32 \ + switch8 \ + switchu8 \ + sync_fetch_and_add_4 \ + sync_fetch_and_sub_4 \ + sync_fetch_and_and_4 \ + sync_fetch_and_or_4 \ + sync_fetch_and_xor_4 \ + sync_fetch_and_nand_4 \ + sync_fetch_and_max_4 \ + sync_fetch_and_umax_4 \ + sync_fetch_and_min_4 \ + sync_fetch_and_umin_4 \ + sync_fetch_and_add_8 \ + sync_fetch_and_sub_8 \ + sync_fetch_and_and_8 \ + sync_fetch_and_or_8 \ + sync_fetch_and_xor_8 \ + sync_fetch_and_nand_8 \ + sync_fetch_and_max_8 \ + sync_fetch_and_umax_8 \ + sync_fetch_and_min_8 \ + sync_fetch_and_umin_8 + +I386_FUNCTIONS := \ + i686.get_pc_thunk.eax \ + i686.get_pc_thunk.ebp \ + i686.get_pc_thunk.ebx \ + i686.get_pc_thunk.ecx \ + i686.get_pc_thunk.edi \ + i686.get_pc_thunk.edx \ + i686.get_pc_thunk.esi + +# FIXME: Currently, compiler-rt is missing implementations for a number of the +# functions. Filter them out for now. +MISSING_FUNCTIONS := \ + cmpdf2 cmpsf2 div0 \ + ffssi2 \ + udiv_w_sdiv unorddf2 unordsf2 bswapdi2 \ + bswapsi2 \ + gcc_bcmp \ + do_global_dtors \ + i686.get_pc_thunk.eax i686.get_pc_thunk.ebp i686.get_pc_thunk.ebx \ + i686.get_pc_thunk.ecx i686.get_pc_thunk.edi i686.get_pc_thunk.edx \ + i686.get_pc_thunk.esi \ + aeabi_cdcmpeq aeabi_cdrcmple aeabi_cfcmpeq aeabi_cfrcmple aeabi_dcmpeq \ + aeabi_dcmpge aeabi_dcmpgt aeabi_dcmple aeabi_dcmplt aeabi_drsub \ + aeabi_fcmpeq \ aeabi_fcmpge aeabi_fcmpgt aeabi_fcmple aeabi_fcmplt \ + aeabi_frsub aeabi_idivmod aeabi_uidivmod + +FUNCTIONS_ARMV6M := $(COMMON_FUNCTIONS) $(ARM_FUNCTIONS) +FUNCTIONS_ARM_ALL := $(COMMON_FUNCTIONS) $(ARM_FUNCTIONS) $(THUMB2_FUNCTIONS) +FUNCTIONS_I386 := $(COMMON_FUNCTIONS) $(I386_FUNCTIONS) +FUNCTIONS_X86_64 := $(COMMON_FUNCTIONS) + +FUNCTIONS_ARMV6M := \ + $(filter-out $(MISSING_FUNCTIONS),$(FUNCTIONS_ARMV6M)) +FUNCTIONS_ARM_ALL := \ + $(filter-out $(MISSING_FUNCTIONS),$(FUNCTIONS_ARM_ALL)) +FUNCTIONS_I386 := \ + $(filter-out $(MISSING_FUNCTIONS),$(FUNCTIONS_I386)) +FUNCTIONS_X86_64 := \ + $(filter-out $(MISSING_FUNCTIONS),$(FUNCTIONS_X86_64)) + +FUNCTIONS.soft_static.armv6m := $(FUNCTIONS_ARMV6M) +FUNCTIONS.soft_pic.armv6m := $(FUNCTIONS_ARMV6M) + +FUNCTIONS.soft_static.armv7m := $(FUNCTIONS_ARM_ALL) +FUNCTIONS.soft_pic.armv7m := $(FUNCTIONS_ARM_ALL) + +FUNCTIONS.soft_static.armv7em := $(FUNCTIONS_ARM_ALL) +FUNCTIONS.hard_static.armv7em := $(FUNCTIONS_ARM_ALL) +FUNCTIONS.soft_pic.armv7em := $(FUNCTIONS_ARM_ALL) +FUNCTIONS.hard_pic.armv7em := $(FUNCTIONS_ARM_ALL) + +FUNCTIONS.soft_static.armv7 := $(FUNCTIONS_ARM_ALL) +FUNCTIONS.hard_static.armv7 := $(FUNCTIONS_ARM_ALL) +FUNCTIONS.soft_pic.armv7 := $(FUNCTIONS_ARM_ALL) +FUNCTIONS.hard_pic.armv7 := $(FUNCTIONS_ARM_ALL) + +FUNCTIONS.hard_static.i386 := $(FUNCTIONS_I386) +FUNCTIONS.hard_pic.i386 := $(FUNCTIONS_I386) + +FUNCTIONS.hard_static.x86_64 := $(FUNCTIONS_X86_64) +FUNCTIONS.hard_pic.x86_64 := $(FUNCTIONS_X86_64) diff --git a/src/compiler-rt/make/platform/clang_macho_embedded_test_input.c b/src/compiler-rt/make/platform/clang_macho_embedded_test_input.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/compiler-rt/make/platform/clang_mingw.mk b/src/compiler-rt/make/platform/clang_mingw.mk new file mode 100644 index 0000000000..2aedbc3526 --- /dev/null +++ b/src/compiler-rt/make/platform/clang_mingw.mk @@ -0,0 +1,30 @@ +Description := Static runtime libraries for mingw-w64 + +### + +CC ?= cc +AR ?= ar + +Arch := unknown +Configs := + +SupportedArches := x86_64 i386 arm + +Configs += builtins-x86_64 builtins-i386 builtins-arm +Arch.builtins-x86_64 := x86_64 +Arch.builtins-i386 := i386 +Arch.builtins-arm := arm + +### + +CFLAGS := -Wall -O3 -fomit-frame-pointer +CFLAGS.builtins-x86_64 := -target x86_64-windows-gnu $(CFLAGS) +CFLAGS.builtins-i386 := -target i686-windows-gnu $(CFLAGS) +CFLAGS.builtins-arm := -target armv7-windows-gnu $(CFLAGS) + +FUNCTIONS.builtins-x86_64 := $(CommonFunctions) $(ArchFunctions.x86_64) +FUNCTIONS.builtins-i386 := $(CommonFunctions) $(ArchFunctions.i386) +FUNCTIONS.builtins-arm := $(CommonFunctions) $(ArchFunctions.arm) + +# Always use optimized variants. +OPTIMIZED := 1 diff --git a/src/compiler-rt/make/platform/darwin_bni.mk b/src/compiler-rt/make/platform/darwin_bni.mk new file mode 100644 index 0000000000..8e066e8e31 --- /dev/null +++ b/src/compiler-rt/make/platform/darwin_bni.mk @@ -0,0 +1,135 @@ + +Description := Target for Darwin using an Apple-style build. + +Configs := Debug Release Profile Static + +# We override this with RC_ARCHS because B&I may want to build on an ARCH we +# haven't explicitly defined support for. If all goes well, this will just work +# and the resulting lib will just have generic versions for anything unknown. +UniversalArchs := $(RC_ARCHS) + +ifneq (,$(SDKROOT)) + override CC := $(shell xcrun -sdk $(SDKROOT) -find clang || echo "false") + AR := $(shell xcrun -sdk $(SDKROOT) -find ar || echo "false") + RANLIB := $(shell xcrun -sdk $(SDKROOT) -find ranlib || echo "false") + STRIP := $(shell xcrun -sdk $(SDKROOT) -find strip || echo "false") + LIPO := $(shell xcrun -sdk $(SDKROOT) -find lipo || echo "false") + DSYMUTIL := $(shell xcrun -sdk $(SDKROOT) -find dsymutil || echo "false") +endif + +ifneq ($(IPHONEOS_DEPLOYMENT_TARGET),) + DEPLOYMENT_FLAGS := -miphoneos-version-min=$(IPHONEOS_DEPLOYMENT_TARGET) +else + ifneq ($(MACOSX_DEPLOYMENT_TARGET),) + DEPLOYMENT_FLAGS := -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) + endif +endif + +ifneq (,$(SDKROOT)) + DEPLOYMENT_FLAGS += -isysroot $(SDKROOT) +endif + +CFLAGS := -Wall -Os -fomit-frame-pointer -g $(DEPLOYMENT_FLAGS) +CFLAGS.Static := $(CFLAGS) -static +DYLIB_FLAGS := $(DEPLOYMENT_FLAGS) \ + -Xarch_arm -Wl,-alias_list,$(SRCROOT)/lib/builtins/arm/softfloat-alias.list + +VISIBILITY_HIDDEN := 0 +VISIBILITY_HIDDEN.Static := 1 + + +FUNCTIONS := absvdi2 absvsi2 addvdi3 addvsi3 ashldi3 ashrdi3 \ + clzdi2 clzsi2 cmpdi2 ctzdi2 ctzsi2 \ + divdc3 divdi3 divsc3 ffsdi2 \ + fixdfdi fixsfdi fixunsdfdi fixunsdfsi fixunssfdi \ + fixunssfsi floatdidf floatdisf floatundidf floatundisf \ + gcc_personality_v0 lshrdi3 moddi3 muldc3 muldi3 mulosi4 \ + mulodi4 muloti4 mulsc3 mulvdi3 mulvsi3 negdi2 negvdi2 negvsi2 \ + paritydi2 paritysi2 popcountdi2 popcountsi2 powidf2 \ + powisf2 subvdi3 subvsi3 ucmpdi2 udivdi3 \ + udivmoddi4 umoddi3 apple_versioning eprintf atomic \ + atomic_flag_clear atomic_flag_clear_explicit \ + atomic_flag_test_and_set atomic_flag_test_and_set_explicit \ + atomic_signal_fence atomic_thread_fence \ + extendhfsf2 truncdfhf2 truncsfhf2 + +FUNCTIONS.i386 := $(FUNCTIONS) \ + divxc3 fixunsxfdi fixunsxfsi fixxfdi floatdixf \ + floatundixf mulxc3 powixf2 clear_cache \ + enable_execute_stack +FUNCTIONS.ppc := $(FUNCTIONS) \ + divtc3 fixtfdi fixunstfdi floatditf floatunditf \ + gcc_qadd gcc_qdiv gcc_qmul gcc_qsub multc3 \ + powitf2 restFP saveFP trampoline_setup \ + clear_cache enable_execute_stack +FUNCTIONS.x86_64 := $(FUNCTIONS) \ + absvti2 addvti3 ashlti3 ashrti3 clzti2 cmpti2 \ + ctzti2 divti3 divxc3 ffsti2 fixdfti fixsfti \ + fixunsdfti fixunssfti fixunsxfdi fixunsxfsi \ + fixunsxfti fixxfdi fixxfti floatdixf floattidf \ + floattisf floattixf floatundixf floatuntidf \ + floatuntisf floatuntixf lshrti3 modti3 multi3 \ + muloti4 mulvti3 mulxc3 negti2 negvti2 parityti2 \ + popcountti2 powixf2 subvti3 ucmpti2 udivmodti4 \ + udivti3 umodti3 clear_cache enable_execute_stack + +FUNCTIONS.armv4t := $(FUNCTIONS) + +FUNCTIONS.armv5 := $(FUNCTIONS) \ + adddf3 addsf3 bswapdi2 bswapsi2 \ + comparedf2 comparesf2 extendsfdf2 \ + divdf3 divsf3 \ + fixdfsi fixsfsi fixunsdfsi fixunssfsi \ + floatsidf floatsisf floatunsidf floatunsisf \ + muldf3 mulsf3 \ + negdf2 negsf2 \ + truncdfsf2 \ + modsi3 umodsi3 udivsi3 divsi3 udivmodsi4 divmodsi4 \ + switch8 switchu8 switch16 switch32 \ + sync_synchronize + +FUNCTIONS.armv6 := $(FUNCTIONS) \ + comparedf2 comparesf2 \ + adddf3vfp addsf3vfp bswapdi2 bswapsi2 divdf3vfp \ + divsf3vfp eqdf2vfp eqsf2vfp extendsfdf2vfp \ + fixdfsivfp fixsfsivfp fixunsdfsivfp fixunssfsivfp \ + floatsidfvfp floatsisfvfp floatunssidfvfp floatunssisfvfp \ + gedf2vfp gesf2vfp gtdf2vfp gtsf2vfp \ + ledf2vfp lesf2vfp ltdf2vfp ltsf2vfp \ + muldf3vfp mulsf3vfp \ + nedf2vfp nesf2vfp \ + subdf3vfp subsf3vfp truncdfsf2vfp unorddf2vfp unordsf2vfp \ + modsi3 umodsi3 udivsi3 divsi3 udivmodsi4 divmodsi4 \ + switch8 switchu8 switch16 switch32 \ + restore_vfp_d8_d15_regs save_vfp_d8_d15_regs \ + sync_synchronize + +FUNCTIONS.armv7 := $(FUNCTIONS) \ + comparedf2 comparesf2 \ + adddf3vfp addsf3vfp bswapdi2 bswapsi2 divdf3vfp \ + divsf3vfp eqdf2vfp eqsf2vfp extendsfdf2vfp \ + fixdfsivfp fixsfsivfp fixunsdfsivfp fixunssfsivfp \ + floatsidfvfp floatsisfvfp floatunssidfvfp floatunssisfvfp \ + gedf2vfp gesf2vfp gtdf2vfp gtsf2vfp \ + ledf2vfp lesf2vfp ltdf2vfp ltsf2vfp \ + muldf3vfp mulsf3vfp \ + nedf2vfp nesf2vfp \ + subdf3vfp subsf3vfp truncdfsf2vfp unorddf2vfp unordsf2vfp \ + modsi3 umodsi3 udivsi3 divsi3 udivmodsi4 divmodsi4 + +FUNCTIONS.armv7s := $(FUNCTIONS.armv7) + +FUNCTIONS.arm64 := divti3 modti3 \ + udivmodti4 \ + udivti3 umodti3 \ + mulsc3 muldc3 \ + powisf2 powidf2 \ + clzti2 \ + fixdfti fixsfti \ + fixunsdfti fixunssfti fixunssfti \ + floattidf floattisf floatuntidf floatuntisf \ + gcc_personality_v0 atomic \ + atomic_flag_clear atomic_flag_clear_explicit \ + atomic_flag_test_and_set \ + atomic_flag_test_and_set_explicit \ + atomic_signal_fence atomic_thread_fence diff --git a/src/compiler-rt/make/platform/multi_arch.mk b/src/compiler-rt/make/platform/multi_arch.mk new file mode 100644 index 0000000000..fe6ac4be0e --- /dev/null +++ b/src/compiler-rt/make/platform/multi_arch.mk @@ -0,0 +1,15 @@ +Description := Example configuration for build two libraries for separate \ +architectures. + +Configs := m32 m64 +Arch := i386 +Arch.m64 := x86_64 + +CC := clang + +CFLAGS := -Wall -Werror +CFLAGS.m32 := $(CFLAGS) -m32 -O3 +CFLAGS.m64 := $(CFLAGS) -m64 -O3 + +FUNCTIONS := moddi3 floatundixf udivdi3 +FUNCTIONS.m64 := $(FUNCTIONS) lshrdi3 diff --git a/src/compiler-rt/make/platform/triple.mk b/src/compiler-rt/make/platform/triple.mk deleted file mode 100644 index 0d68b2eafd..0000000000 --- a/src/compiler-rt/make/platform/triple.mk +++ /dev/null @@ -1,78 +0,0 @@ -# This "platform" file is intended for building compiler-rt using gcc. -# The actual target platform is selected by setting the TargetTriple variable to the corresponding LLVM triple. - -Description := Static runtime libraries for platforms selected by 'TargetTriple' - -# Provide defaults for the required vars -ifndef CC - CC := gcc -endif -ifndef CFLAGS - CFLAGS := -Wall -O3 -endif - -Configs := builtins - -Arch := $(word 1,$(subst -, ,$(TargetTriple))) -ifeq ($(Arch),i686) - Arch := i386 -else ifeq ($(Arch),arm) -ifneq (,$(findstring ios,$(TargetTriple))) - Arch := armv7 -else ifneq (,$(findstring android,$(TargetTriple))) - Arch := armv7 -endif -endif - -# Filter out stuff that gcc cannot compile (these are only needed for clang-generated code anywasys). -CommonFunctions_gcc := $(filter-out atomic% enable_execute_stack,$(CommonFunctions)) - -# Filter out stuff which is not available on specific target -# For example, sync_fetch_and_add_4 uses Thumb instructions, which are unavailable -# when building for arm-linux-androideabi -ifeq ($(TargetTriple),arm-linux-androideabi) - ArchDisabledFunctions := \ - sync_fetch_and_add_4 \ - sync_fetch_and_sub_4 \ - sync_fetch_and_and_4 \ - sync_fetch_and_or_4 \ - sync_fetch_and_xor_4 \ - sync_fetch_and_nand_4 \ - sync_fetch_and_max_4 \ - sync_fetch_and_umax_4 \ - sync_fetch_and_min_4 \ - sync_fetch_and_umin_4 \ - sync_fetch_and_add_8 \ - sync_fetch_and_sub_8 \ - sync_fetch_and_and_8 \ - sync_fetch_and_or_8 \ - sync_fetch_and_xor_8 \ - sync_fetch_and_nand_8 \ - sync_fetch_and_max_8 \ - sync_fetch_and_umax_8 \ - sync_fetch_and_min_8 \ - sync_fetch_and_umin_8 -endif - -# Disable emutls on MIPS -# Rust uses GCC 4.4 to cross-compile, which doesn't have some builtins -ifneq (,$(findstring mips,$(TargetTriple))) - CommonDisabledFunctions := emutls -endif - -# Disable emutls on Windows -# emutls works on POSIX only as it uses pthreads -ifneq (,$(findstring windows,$(TargetTriple))) - CommonDisabledFunctions := emutls -endif - -# Clear cache is builtin on aarch64-apple-ios -# arm64 and aarch64 are synonims, but iOS targets usually use arm64 (history reasons) -ifeq (aarch64-apple-ios,$(subst arm64,aarch64,$(TargetTriple))) -CommonDisabledFunctions := clear_cache -endif - -ArchEnabledFunctions := $(filter-out $(ArchDisabledFunctions),$(value ArchFunctions.$(Arch))) -CommonEnabledFunctions := $(filter-out $(CommonDisabledFunctions),$(CommonFunctions_gcc)) - -FUNCTIONS.builtins := $(CommonEnabledFunctions) $(ArchEnabledFunctions) diff --git a/src/compiler-rt/test/CMakeLists.txt b/src/compiler-rt/test/CMakeLists.txt index 684b409bb8..e5c51c8cd4 100644 --- a/src/compiler-rt/test/CMakeLists.txt +++ b/src/compiler-rt/test/CMakeLists.txt @@ -19,8 +19,8 @@ if(NOT ANDROID) if(NOT COMPILER_RT_STANDALONE_BUILD) # Use LLVM utils and Clang from the same build tree. list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS - clang clang-headers FileCheck count not llvm-config llvm-nm llvm-symbolizer - compiler-rt-headers) + clang clang-headers FileCheck count not llvm-config llvm-nm llvm-objdump + llvm-symbolizer compiler-rt-headers) if (COMPILER_RT_HAS_PROFILE) list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS profile) endif() diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer-dyld-root-path.cc b/src/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer-dyld-root-path.cc index aa881ae134..4595fb547f 100644 --- a/src/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer-dyld-root-path.cc +++ b/src/compiler-rt/test/asan/TestCases/Darwin/atos-symbolizer-dyld-root-path.cc @@ -1,9 +1,10 @@ // Check that when having a DYLD_ROOT_PATH set, the symbolizer still works. +// RUN: %clangxx_asan -O0 %s -o %t // RUN: %env_asan_opts=verbosity=2 DYLD_ROOT_PATH="/" ASAN_SYMBOLIZER_PATH=$(which atos) \ // RUN: not %run %t 2>&1 | FileCheck %s // // Due to a bug in atos, this only works on x86_64. -// REQUIRES: x86_64 +// REQUIRES: asan-64-bits #include #include @@ -16,11 +17,11 @@ int main(int argc, char **argv) { // 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: #1 0x{{.*}} in main {{.*}}atos-symbolizer-dyld-root-path.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: #1 0x{{.*}} in main {{.*}}atos-symbolizer-dyld-root-path.cc:[[@LINE-8]] // CHECK: allocated by thread T0 here: - // CHECK: atos-symbolizer.cc:[[@LINE-13]] + // CHECK: atos-symbolizer-dyld-root-path.cc:[[@LINE-13]] return res; } diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/crashlog-stacktraces.c b/src/compiler-rt/test/asan/TestCases/Darwin/crashlog-stacktraces.c index e9af5396e1..9151614819 100644 --- a/src/compiler-rt/test/asan/TestCases/Darwin/crashlog-stacktraces.c +++ b/src/compiler-rt/test/asan/TestCases/Darwin/crashlog-stacktraces.c @@ -1,6 +1,11 @@ // RUN: %clang_asan -O0 %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s +// Since ASan is built with -fomit-frame-pointer, backtrace is not able to +// symbolicate the trace past ASan runtime on i386. (This is fixed in +// latest OS X.) +// REQUIRES: asan-64-bits + #include #include #include diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc b/src/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc index 7e8d9173d2..b22036a7ef 100644 --- a/src/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc +++ b/src/compiler-rt/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc @@ -37,10 +37,10 @@ int main() { // CHECK-NOINSERT: exec()-ing the program with // CHECK-NOINSERT: DYLD_INSERT_LIBRARIES -// CHECK-NOINSERT: to enable ASan wrappers. +// CHECK-NOINSERT: to enable wrappers. // CHECK-NOINSERT: Passed // CHECK-NOT: exec()-ing the program with // CHECK-NOT: DYLD_INSERT_LIBRARIES -// CHECK-NOT: to enable ASan wrappers. +// CHECK-NOT: to enable wrappers. // CHECK: Passed diff --git a/src/compiler-rt/test/asan/TestCases/Darwin/interface_symbols_darwin.c b/src/compiler-rt/test/asan/TestCases/Darwin/interface_symbols_darwin.c index 9bd32869c9..ed5779ebe2 100644 --- a/src/compiler-rt/test/asan/TestCases/Darwin/interface_symbols_darwin.c +++ b/src/compiler-rt/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_load1_noabort >> %t.interface +// RUN: echo __asan_report_load2_noabort >> %t.interface +// RUN: echo __asan_report_load4_noabort >> %t.interface +// RUN: echo __asan_report_load8_noabort >> %t.interface +// RUN: echo __asan_report_load16_noabort >> %t.interface +// RUN: echo __asan_report_store1_noabort >> %t.interface +// RUN: echo __asan_report_store2_noabort >> %t.interface +// RUN: echo __asan_report_store4_noabort >> %t.interface +// RUN: echo __asan_report_store8_noabort >> %t.interface +// RUN: echo __asan_report_store16_noabort >> %t.interface +// RUN: echo __asan_report_load_n_noabort >> %t.interface +// RUN: echo __asan_report_store_n_noabort >> %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 diff --git a/src/compiler-rt/test/asan/TestCases/Linux/calloc-preload.c b/src/compiler-rt/test/asan/TestCases/Linux/calloc-preload.c new file mode 100644 index 0000000000..eb1c6738b6 --- /dev/null +++ b/src/compiler-rt/test/asan/TestCases/Linux/calloc-preload.c @@ -0,0 +1,36 @@ +// Test that initially callocked memory is properly freed +// (see https://github.com/google/sanitizers/issues/626). +// +// RUN: %clang %s -o %t +// RUN: env LD_PRELOAD=%shared_libasan %run %t +// +// REQUIRES: asan-dynamic-runtime +// +// This way of setting LD_PRELOAD does not work with Android test runner. +// REQUIRES: not-android + +#include +#include + +static void *ptr; + +// This constructor will run before __asan_init +// so calloc will allocate memory from special pool. +static void init() { + ptr = calloc(10, 1); +} + +__attribute__((section(".preinit_array"), used)) +void *dummy = init; + +void free_memory() { + // This used to abort because + // Asan's free didn't recognize ptr. + free(ptr); +} + +int main() { + free_memory(); + return 0; +} + diff --git a/src/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.c b/src/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.c index beb44bdc0b..971feb5dc0 100644 --- a/src/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.c +++ b/src/compiler-rt/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_load1_noabort >> %t.interface +// RUN: echo __asan_report_load2_noabort >> %t.interface +// RUN: echo __asan_report_load4_noabort >> %t.interface +// RUN: echo __asan_report_load8_noabort >> %t.interface +// RUN: echo __asan_report_load16_noabort >> %t.interface +// RUN: echo __asan_report_store1_noabort >> %t.interface +// RUN: echo __asan_report_store2_noabort >> %t.interface +// RUN: echo __asan_report_store4_noabort >> %t.interface +// RUN: echo __asan_report_store8_noabort >> %t.interface +// RUN: echo __asan_report_store16_noabort >> %t.interface +// RUN: echo __asan_report_load_n_noabort >> %t.interface +// RUN: echo __asan_report_store_n_noabort >> %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 diff --git a/src/compiler-rt/test/asan/TestCases/Linux/mincore.cc b/src/compiler-rt/test/asan/TestCases/Linux/mincore.cc new file mode 100644 index 0000000000..30f450830f --- /dev/null +++ b/src/compiler-rt/test/asan/TestCases/Linux/mincore.cc @@ -0,0 +1,34 @@ +// RUN: %clangxx_asan -std=c++11 -O0 %s -o %t && %run %t + +#include +#include +#include + +int main(void) { + unsigned char vec[20]; + int res; + size_t PS = sysconf(_SC_PAGESIZE); + void *addr = mmap(nullptr, 20 * PS, PROT_READ | PROT_WRITE, + MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + + res = mincore(addr, 10 * PS, vec); + assert(res == 0); + for (int i = 0; i < 10; ++i) + assert((vec[i] & 1) == 0); + + for (int i = 0; i < 5; ++i) + ((char *)addr)[i * PS] = 1; + res = mincore(addr, 10 * PS, vec); + assert(res == 0); + for (int i = 0; i < 10; ++i) + assert((vec[i] & 1) == (i < 5)); + + for (int i = 5; i < 10; ++i) + ((char *)addr)[i * PS] = 1; + res = mincore(addr, 10 * PS, vec); + assert(res == 0); + for (int i = 0; i < 10; ++i) + assert((vec[i] & 1) == 1); + + return 0; +} diff --git a/src/compiler-rt/test/asan/TestCases/Linux/static_tls.cc b/src/compiler-rt/test/asan/TestCases/Linux/static_tls.cc index ff699f3d60..11bb1a4f84 100644 --- a/src/compiler-rt/test/asan/TestCases/Linux/static_tls.cc +++ b/src/compiler-rt/test/asan/TestCases/Linux/static_tls.cc @@ -9,7 +9,7 @@ // CHECK: __tls_get_addr: static tls // CHECK: after -// XFAIL: powerpc64, aarch64 +// XFAIL: aarch64 #ifndef SHARED #include diff --git a/src/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c b/src/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c new file mode 100644 index 0000000000..60916f6570 --- /dev/null +++ b/src/compiler-rt/test/asan/TestCases/Posix/halt_on_error-signals.c @@ -0,0 +1,102 @@ +// Test interaction of Asan recovery mode with asynch signals. +// +// RUN: %clang_asan -fsanitize-recover=address -pthread %s -o %t +// +// RUN: rm -f %t.log +// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 100 >%t.log 2>&1 || true +// Collision will almost always get triggered but we still need to check the unlikely case: +// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < %t.log || FileCheck --check-prefix=CHECK-NO-COLLISION %s < %t.log + +#define _SVID_SOURCE 1 // SA_NODEFER + +#include +#include +#include +#include +#include +#include + +#include + +void random_delay(unsigned *seed) { + *seed = 1664525 * *seed + 1013904223; + struct timespec delay = { 0, (*seed % 1000) * 1000 }; + nanosleep(&delay, 0); +} + +volatile char bad[2] = {1, }; + +void error() { + // CHECK-COLLISION: AddressSanitizer: nested bug in the same thread, aborting + // CHECK-NO-COLLISION: AddressSanitizer: use-after-poison + volatile int idx = 0; + bad[idx] = 0; +} + +#define CHECK_CALL(e, msg) do { \ + if (0 != (e)) { \ + fprintf(stderr, "Failed to " msg "\n"); \ + exit(1); \ + } \ +} while (0) + +size_t niter = 10; +pthread_t sender_tid, receiver_tid; + +pthread_mutex_t keep_alive_mu = PTHREAD_MUTEX_INITIALIZER; + +void *sender(void *arg) { + unsigned seed = 0; + for (size_t i = 0; i < niter; ++i) { + random_delay(&seed); + CHECK_CALL(pthread_kill(receiver_tid, SIGUSR1), "send signal"); + } + return 0; +} + +void handler(int sig) { + // Expect error collisions here + error(); +} + +void *receiver(void *arg) { + unsigned seed = 1; + for (size_t i = 0; i < niter; ++i) { + random_delay(&seed); + // And here + error(); + } + // Parent will release this when it's ok to terminate + CHECK_CALL(pthread_mutex_lock(&keep_alive_mu), "unlock mutex"); + return 0; +} + +int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "Syntax: %s niter\n", argv[0]); + exit(1); + } + + niter = (size_t)strtoul(argv[1], 0, 0); + + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = handler; + sa.sa_flags = SA_NODEFER; // Enable nested handlers to add more stress + CHECK_CALL(sigaction(SIGUSR1, &sa, 0), "set sighandler"); + + __asan_poison_memory_region(&bad, sizeof(bad)); + + CHECK_CALL(pthread_mutex_lock(&keep_alive_mu), "lock mutex"); + CHECK_CALL(pthread_create(&receiver_tid, 0, receiver, 0), "start thread"); + CHECK_CALL(pthread_create(&sender_tid, 0, sender, 0), "start thread"); + CHECK_CALL(pthread_join(sender_tid, 0), "join thread"); + // Now allow receiver to die + CHECK_CALL(pthread_mutex_unlock(&keep_alive_mu), "unlock mutex"); + CHECK_CALL(pthread_join(receiver_tid, 0), "join thread"); + + // CHECK-NO-COLLISION: All threads terminated + printf("All threads terminated\n"); + + return 0; +} diff --git a/src/compiler-rt/test/asan/TestCases/Posix/halt_on_error-torture.cc b/src/compiler-rt/test/asan/TestCases/Posix/halt_on_error-torture.cc new file mode 100644 index 0000000000..019f7d126a --- /dev/null +++ b/src/compiler-rt/test/asan/TestCases/Posix/halt_on_error-torture.cc @@ -0,0 +1,87 @@ +// Stress test recovery mode with many threads. +// +// RUN: %clangxx_asan -fsanitize-recover=address -pthread %s -o %t +// +// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 1 10 >1.txt 2>&1 +// RUN: FileCheck %s < 1.txt +// RUN: [ $(grep -c 'ERROR: AddressSanitizer: use-after-poison' 1.txt) -eq 10 ] +// RUN: FileCheck --check-prefix=CHECK-NO-COLLISION %s < 1.txt +// +// Collisions are unlikely but still possible so we need the ||. +// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 10 20 >10.txt 2>&1 || true +// This one is racy although _very_ unlikely to fail: +// RUN: FileCheck %s < 10.txt +// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 1.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 1.txt +// +// Collisions are unlikely but still possible so we need the ||. +// RUN: %env_asan_opts=halt_on_error=false %run %t 10 20 >10.txt 2>&1 || true +// This one is racy although _very_ unlikely to fail: +// RUN: FileCheck %s < 10.txt +// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 1.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 1.txt + +#include +#include +#include +#include + +#include + +size_t nthreads = 10; +size_t niter = 10; + +void random_delay(unsigned *seed) { + *seed = 1664525 * *seed + 1013904223; + struct timespec delay = { 0, (*seed % 1000) * 1000 }; + nanosleep(&delay, 0); +} + +void *run(void *arg) { + unsigned seed = (unsigned)(size_t)arg; + + volatile char tmp[2]; + __asan_poison_memory_region(&tmp, sizeof(tmp)); + + for (size_t i = 0; i < niter; ++i) { + random_delay(&seed); + // Expect error collisions here + // CHECK: ERROR: AddressSanitizer: use-after-poison + volatile int idx = 0; + tmp[idx] = 0; + } + + return 0; +} + +int main(int argc, char **argv) { + if (argc != 3) { + fprintf(stderr, "Syntax: %s nthreads niter\n", argv[0]); + exit(1); + } + + nthreads = (size_t)strtoul(argv[1], 0, 0); + niter = (size_t)strtoul(argv[2], 0, 0); + + pthread_t *tids = new pthread_t[nthreads]; + + for (size_t i = 0; i < nthreads; ++i) { + if (0 != pthread_create(&tids[i], 0, run, (void *)i)) { + fprintf(stderr, "Failed to create thread\n"); + exit(1); + } + } + + for (size_t i = 0; i < nthreads; ++i) { + if (0 != pthread_join(tids[i], 0)) { + fprintf(stderr, "Failed to join thread\n"); + exit(1); + } + } + + // CHECK-COLLISION: AddressSanitizer: nested bug in the same thread, aborting + // CHECK-NO-COLLISION: All threads terminated + printf("All threads terminated\n"); + + delete [] tids; + + return 0; +} diff --git a/src/compiler-rt/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc b/src/compiler-rt/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc new file mode 100644 index 0000000000..98b034812e --- /dev/null +++ b/src/compiler-rt/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc @@ -0,0 +1,55 @@ +// Test reports dedupication for recovery mode. +// +// RUN: %clang_asan -fsanitize-recover=address %s -o %t +// +// Check for reports dedupication. +// RUN: %env_asan_opts=halt_on_error=false %run %t 2>&1 | FileCheck %s +// +// Check that we die after reaching different reports number threshold. +// RUN: %env_asan_opts=halt_on_error=false not %run %t 1 > %t1.log 2>&1 +// RUN: [ $(grep -c 'ERROR: AddressSanitizer: stack-buffer-overflow' %t1.log) -eq 25 ] +// +// Check suppress_equal_pcs=true behavior is equal to default one. +// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=true %run %t 2>&1 | FileCheck %s +// +// Check suppress_equal_pcs=false behavior isn't equal to default one. +// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t > %t2.log 2>&1 +// RUN: [ $(grep -c 'ERROR: AddressSanitizer: stack-buffer-overflow' %t2.log) -eq 30 ] + +#define ACCESS_ARRAY_FIVE_ELEMENTS(array, i) \ + array[i] = i; \ + array[i + 1] = i + 1; \ + array[i + 2] = i + 2; \ + array[i + 3] = i + 3; \ + array[i + 4] = i + 4; \ + +volatile int ten = 10; +unsigned kNumIterations = 10; + +int main(int argc, char **argv) { + char a[10]; + char b[10]; + + if (argc == 1) { + for (int i = 0; i < kNumIterations; ++i) { + // CHECK: READ of size 1 + volatile int res = a[ten + i]; + // CHECK: WRITE of size 1 + a[i + ten] = res + 3; + // CHECK: READ of size 1 + res = a[ten + i]; + // CHECK-NOT: ERROR + } + } else { + for (int i = 0; i < kNumIterations; ++i) { + ACCESS_ARRAY_FIVE_ELEMENTS(a, ten); + ACCESS_ARRAY_FIVE_ELEMENTS(a, ten + 5); + ACCESS_ARRAY_FIVE_ELEMENTS(a, ten + 10); + ACCESS_ARRAY_FIVE_ELEMENTS(b, ten); + ACCESS_ARRAY_FIVE_ELEMENTS(b, ten + 5); + ACCESS_ARRAY_FIVE_ELEMENTS(b, ten + 10); + } + } + return 0; +} + diff --git a/src/compiler-rt/test/asan/TestCases/alloca_vla_interact.cc b/src/compiler-rt/test/asan/TestCases/alloca_vla_interact.cc index e86616f112..3873c3fcee 100644 --- a/src/compiler-rt/test/asan/TestCases/alloca_vla_interact.cc +++ b/src/compiler-rt/test/asan/TestCases/alloca_vla_interact.cc @@ -2,7 +2,6 @@ // RUN: %run %t 2>&1 // // REQUIRES: stable-runtime -// XFAIL: powerpc64 // This testcase checks correct interaction between VLAs and allocas. diff --git a/src/compiler-rt/test/asan/TestCases/coverage-pc-buffer.cc b/src/compiler-rt/test/asan/TestCases/coverage-pc-buffer.cc new file mode 100644 index 0000000000..67b6935ec6 --- /dev/null +++ b/src/compiler-rt/test/asan/TestCases/coverage-pc-buffer.cc @@ -0,0 +1,48 @@ +// Test __sanitizer_coverage_pc_buffer(). + +// RUN: %clangxx_asan -fsanitize-coverage=edge %s -o %t && %run %t + +// UNSUPPORTED: android + +#include +#include +#include + +static volatile int sink; +__attribute__((noinline)) void bar() { sink = 2; } +__attribute__((noinline)) void foo() { sink = 1; } + +void assertNotZeroPcs(uintptr_t *buf, uintptr_t size) { + assert(buf); + for (uintptr_t i = 0; i < size; ++i) + assert(buf[i]); +} + +int main() { + uintptr_t *buf = NULL; + uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf); + assertNotZeroPcs(buf, sz); + assert(sz); + + foo(); + bar(); + uintptr_t *buf1 = NULL; + uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer(&buf1); + assertNotZeroPcs(buf1, sz1); + assert(buf1 == buf); + assert(sz1 > sz); + + bar(); + uintptr_t *buf2 = NULL; + uintptr_t sz2 = __sanitizer_get_coverage_pc_buffer(&buf2); + assertNotZeroPcs(buf2, sz2); + assert(buf2 == buf); + assert(sz2 > sz1); + + __sanitizer_reset_coverage(); + uintptr_t *buf3 = NULL; + uintptr_t sz3 = __sanitizer_get_coverage_pc_buffer(&buf3); + assertNotZeroPcs(buf3, sz3); + assert(buf3 == buf); + assert(sz3 < sz2); +} diff --git a/src/compiler-rt/test/asan/TestCases/coverage-reset.cc b/src/compiler-rt/test/asan/TestCases/coverage-reset.cc index 1f5eed4c85..eb8da8c1aa 100644 --- a/src/compiler-rt/test/asan/TestCases/coverage-reset.cc +++ b/src/compiler-rt/test/asan/TestCases/coverage-reset.cc @@ -42,6 +42,7 @@ int main() { assert(IS_POWER_OF_TWO(bar_bit)); __sanitizer_reset_coverage(); + assert(__sanitizer_get_total_unique_coverage() == 0); GET_AND_PRINT_COVERAGE(); assert(bitset == 0); diff --git a/src/compiler-rt/test/asan/TestCases/halt_on_error-1.c b/src/compiler-rt/test/asan/TestCases/halt_on_error-1.c new file mode 100644 index 0000000000..63c65e58bb --- /dev/null +++ b/src/compiler-rt/test/asan/TestCases/halt_on_error-1.c @@ -0,0 +1,29 @@ +// Test recovery mode. +// +// RUN: %clang_asan -fsanitize-recover=address %s -o %t +// +// RUN: env not %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=halt_on_error=true not %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=halt_on_error=false %run %t 2>&1 | FileCheck %s --check-prefix CHECK-RECOVER + +#include + +volatile int ten = 10; + +int main() { + char x[10]; + // CHECK: WRITE of size 11 + // CHECK-RECOVER: WRITE of size 11 + memset(x, 0, 11); + // CHECK-NOT: READ of size 1 + // CHECK-RECOVER: READ of size 1 + volatile int res = x[ten]; + // CHECK-NOT: WRITE of size 1 + // CHECK-RECOVER: WRITE of size 1 + x[ten] = res + 3; + // CHECK-NOT: READ of size 1 + // CHECK-RECOVER: READ of size 1 + res = x[ten]; + return 0; +} + diff --git a/src/compiler-rt/test/asan/TestCases/speculative_load2.cc b/src/compiler-rt/test/asan/TestCases/speculative_load2.cc new file mode 100644 index 0000000000..51051eb2b7 --- /dev/null +++ b/src/compiler-rt/test/asan/TestCases/speculative_load2.cc @@ -0,0 +1,24 @@ +// Verifies that speculative loads from unions do not happen under asan. +// RUN: %clangxx_asan -O0 %s -o %t && %run %t 2>&1 +// RUN: %clangxx_asan -O1 %s -o %t && %run %t 2>&1 +// RUN: %clangxx_asan -O2 %s -o %t && %run %t 2>&1 +// RUN: %clangxx_asan -O3 %s -o %t && %run %t 2>&1 + +typedef union { + short q; + struct { + short x; + short y; + int for_alignment; + } w; +} U; + +int main() { + char *buf = new char[2]; + buf[0] = buf[1] = 0x0; + U *u = (U *)buf; + short result = u->q == 0 ? 0 : u->w.y; + delete[] buf; + return result; +} + diff --git a/src/compiler-rt/test/asan/TestCases/throw_catch.cc b/src/compiler-rt/test/asan/TestCases/throw_catch.cc index bce48199db..01083510c3 100644 --- a/src/compiler-rt/test/asan/TestCases/throw_catch.cc +++ b/src/compiler-rt/test/asan/TestCases/throw_catch.cc @@ -1,8 +1,5 @@ // RUN: %clangxx_asan -O %s -o %t && %run %t -// Clang doesn't support exceptions on Windows yet. -// XFAIL: win32 - #include #include #include diff --git a/src/compiler-rt/test/asan/lit.cfg b/src/compiler-rt/test/asan/lit.cfg index fd99f66996..835547090a 100644 --- a/src/compiler-rt/test/asan/lit.cfg +++ b/src/compiler-rt/test/asan/lit.cfg @@ -34,7 +34,9 @@ default_asan_opts = '' if config.host_os == 'Darwin': # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. + # Also, make sure we do not overwhelm the syslog while testing. default_asan_opts = 'abort_on_error=0' + default_asan_opts += ':log_to_syslog=0' if default_asan_opts: config.environment['ASAN_OPTIONS'] = default_asan_opts default_asan_opts += ':' diff --git a/src/compiler-rt/test/builtins/Unit/divtc3_test.c b/src/compiler-rt/test/builtins/Unit/divtc3_test.c index ad2c96dc04..a1f0613441 100644 --- a/src/compiler-rt/test/builtins/Unit/divtc3_test.c +++ b/src/compiler-rt/test/builtins/Unit/divtc3_test.c @@ -13,8 +13,6 @@ #include -#if _ARCH_PPC - #include "int_lib.h" #include #include @@ -104,7 +102,7 @@ int test__divtc3(long double a, long double b, long double c, long double d) { long double _Complex z = (a * c + b * d) / (c * c + d * d) + (b * c - a * d) / (c * c + d * d) * _Complex_I; - if (cabs((r - z)/r) > 1.e-6) + if (cabsl((r - z)/r) > 1.e-6) return 1; } break; @@ -358,11 +356,8 @@ long double x[][2] = }; -#endif - int main() { -#if _ARCH_PPC const unsigned N = sizeof(x) / sizeof(x[0]); unsigned i, j; for (i = 0; i < N; ++i) @@ -373,11 +368,7 @@ int main() return 1; } } - -// printf("No errors found.\n"); -#else - printf("skipped\n"); -#endif +// printf("No errors found.\n"); return 0; } diff --git a/src/compiler-rt/test/cfi/CMakeLists.txt b/src/compiler-rt/test/cfi/CMakeLists.txt index 09672953b5..5626a6e50e 100644 --- a/src/compiler-rt/test/cfi/CMakeLists.txt +++ b/src/compiler-rt/test/cfi/CMakeLists.txt @@ -9,6 +9,9 @@ if(NOT COMPILER_RT_STANDALONE_BUILD) opt ubsan ) + if(COMPILER_RT_HAS_CFI) + list(APPEND CFI_TEST_DEPS cfi) + endif() if(LLVM_ENABLE_PIC AND LLVM_BINUTILS_INCDIR) list(APPEND CFI_TEST_DEPS LLVMgold diff --git a/src/compiler-rt/test/cfi/base-derived-destructor.cpp b/src/compiler-rt/test/cfi/base-derived-destructor.cpp index 9655891efb..c5e9db1092 100644 --- a/src/compiler-rt/test/cfi/base-derived-destructor.cpp +++ b/src/compiler-rt/test/cfi/base-derived-destructor.cpp @@ -82,7 +82,7 @@ int main() { fprintf(stderr, "1\n"); // CFI-DIAG: runtime error: control flow integrity check for type 'B' failed during base-to-derived cast - // CFI-DIAG-NEXT: note: vtable is of type 'A' + // CFI-DIAG-NEXT: note: vtable is of type '{{(class )?}}A<{{(class )?}}B>' B* b = new B; break_optimization(b); delete b; // UB here diff --git a/src/compiler-rt/test/cfi/cross-dso/icall/icall-from-dso.cpp b/src/compiler-rt/test/cfi/cross-dso/icall/icall-from-dso.cpp new file mode 100644 index 0000000000..1995f05f43 --- /dev/null +++ b/src/compiler-rt/test/cfi/cross-dso/icall/icall-from-dso.cpp @@ -0,0 +1,26 @@ +// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t-so.so +// RUN: %clangxx_cfi_dso %s -o %t %t-so.so && %expect_crash %t 2>&1 | FileCheck %s + +#include + +#ifdef SHARED_LIB +void g(); +void f() { + // CHECK: =1= + fprintf(stderr, "=1=\n"); + ((void (*)(void))g)(); + // CHECK: =2= + fprintf(stderr, "=2=\n"); + ((void (*)(int))g)(42); // UB here + // CHECK-NOT: =3= + fprintf(stderr, "=3=\n"); +} +#else +void f(); +void g() { +} + +int main() { + f(); +} +#endif diff --git a/src/compiler-rt/test/cfi/cross-dso/icall/icall.cpp b/src/compiler-rt/test/cfi/cross-dso/icall/icall.cpp new file mode 100644 index 0000000000..d7cc2f9ca9 --- /dev/null +++ b/src/compiler-rt/test/cfi/cross-dso/icall/icall.cpp @@ -0,0 +1,21 @@ +// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t-so.so +// RUN: %clangxx_cfi_dso %s -o %t %t-so.so && %expect_crash %t 2>&1 | FileCheck %s + +#include + +#ifdef SHARED_LIB +void f() { +} +#else +void f(); +int main() { + // CHECK: =1= + fprintf(stderr, "=1=\n"); + ((void (*)(void))f)(); + // CHECK: =2= + fprintf(stderr, "=2=\n"); + ((void (*)(int))f)(42); // UB here + // CHECK-NOT: =3= + fprintf(stderr, "=3=\n"); +} +#endif diff --git a/src/compiler-rt/test/cfi/cross-dso/icall/lit.local.cfg b/src/compiler-rt/test/cfi/cross-dso/icall/lit.local.cfg new file mode 100644 index 0000000000..db08765a2b --- /dev/null +++ b/src/compiler-rt/test/cfi/cross-dso/icall/lit.local.cfg @@ -0,0 +1,3 @@ +# The cfi-icall checker is only supported on x86 and x86_64 for now. +if config.root.host_arch not in ['x86', 'x86_64']: + config.unsupported = True diff --git a/src/compiler-rt/test/cfi/cross-dso/lit.local.cfg b/src/compiler-rt/test/cfi/cross-dso/lit.local.cfg new file mode 100644 index 0000000000..57271b8078 --- /dev/null +++ b/src/compiler-rt/test/cfi/cross-dso/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/src/compiler-rt/test/cfi/cross-dso/simple-fail.cpp b/src/compiler-rt/test/cfi/cross-dso/simple-fail.cpp new file mode 100644 index 0000000000..64db288a95 --- /dev/null +++ b/src/compiler-rt/test/cfi/cross-dso/simple-fail.cpp @@ -0,0 +1,92 @@ +// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t1-so.so +// RUN: %clangxx_cfi_dso %s -o %t1 %t1-so.so +// RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %expect_crash %t1 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s + +// RUN: %clangxx_cfi_dso -DB32 -DSHARED_LIB %s -fPIC -shared -o %t2-so.so +// RUN: %clangxx_cfi_dso -DB32 %s -o %t2 %t2-so.so +// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %expect_crash %t2 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s + +// RUN: %clangxx_cfi_dso -DB64 -DSHARED_LIB %s -fPIC -shared -o %t3-so.so +// RUN: %clangxx_cfi_dso -DB64 %s -o %t3 %t3-so.so +// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %expect_crash %t3 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s + +// RUN: %clangxx_cfi_dso -DBM -DSHARED_LIB %s -fPIC -shared -o %t4-so.so +// RUN: %clangxx_cfi_dso -DBM %s -o %t4 %t4-so.so +// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %expect_crash %t4 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s + +// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %t5-so.so +// RUN: %clangxx -DBM %s -o %t5 %t5-so.so +// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s +// RUN: %t5 x 2>&1 | FileCheck --check-prefix=NCFI %s + +// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %t6-so.so +// RUN: %clangxx_cfi_dso -DBM %s -o %t6 %t6-so.so +// RUN: %t6 2>&1 | FileCheck --check-prefix=NCFI %s +// RUN: %t6 x 2>&1 | FileCheck --check-prefix=NCFI %s + +// Tests that the CFI mechanism crashes the program when making a virtual call +// to an object of the wrong class but with a compatible vtable, by casting a +// pointer to such an object and attempting to make a call through it. + +// REQUIRES: cxxabi + +#include +#include + +struct A { + virtual void f(); +}; + +void *create_B(); + +#ifdef SHARED_LIB + +#include "../utils.h" +struct B { + virtual void f(); +}; +void B::f() {} + +void *create_B() { + create_derivers(); + return (void *)(new B()); +} + +#else + +void A::f() {} + +int main(int argc, char *argv[]) { + void *p = create_B(); + A *a; + + // CFI: =0= + // CFI-CAST: =0= + // NCFI: =0= + fprintf(stderr, "=0=\n"); + + if (argc > 1 && argv[1][0] == 'x') { + // Test cast. BOOM. + a = (A*)p; + } else { + // Invisible to CFI. Test virtual call later. + memcpy(&a, &p, sizeof(a)); + } + + // CFI: =1= + // CFI-CAST-NOT: =1= + // NCFI: =1= + fprintf(stderr, "=1=\n"); + + a->f(); // UB here + + // CFI-NOT: =2= + // CFI-CAST-NOT: =2= + // NCFI: =2= + fprintf(stderr, "=2=\n"); +} +#endif diff --git a/src/compiler-rt/test/cfi/cross-dso/simple-pass.cpp b/src/compiler-rt/test/cfi/cross-dso/simple-pass.cpp new file mode 100644 index 0000000000..42f7a27345 --- /dev/null +++ b/src/compiler-rt/test/cfi/cross-dso/simple-pass.cpp @@ -0,0 +1,65 @@ +// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t1-so.so +// RUN: %clangxx_cfi_dso %s -o %t1 %t1-so.so +// RUN: %t1 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi_dso -DB32 -DSHARED_LIB %s -fPIC -shared -o %t2-so.so +// RUN: %clangxx_cfi_dso -DB32 %s -o %t2 %t2-so.so +// RUN: %t2 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi_dso -DB64 -DSHARED_LIB %s -fPIC -shared -o %t3-so.so +// RUN: %clangxx_cfi_dso -DB64 %s -o %t3 %t3-so.so +// RUN: %t3 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi_dso -DBM -DSHARED_LIB %s -fPIC -shared -o %t4-so.so +// RUN: %clangxx_cfi_dso -DBM %s -o %t4 %t4-so.so +// RUN: %t4 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %t5-so.so +// RUN: %clangxx -DBM %s -o %t5 %t5-so.so +// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s +// RUN: %t5 x 2>&1 | FileCheck --check-prefix=NCFI %s + +// Tests that the CFI mechanism crashes the program when making a virtual call +// to an object of the wrong class but with a compatible vtable, by casting a +// pointer to such an object and attempting to make a call through it. + +// REQUIRES: cxxabi + +#include +#include + +struct A { + virtual void f(); +}; + +A *create_B(); + +#ifdef SHARED_LIB + +#include "../utils.h" +struct B : public A { + virtual void f(); +}; +void B::f() {} + +A *create_B() { + create_derivers(); + return new B(); +} + +#else + +void A::f() {} + +int main(int argc, char *argv[]) { + A *a = create_B(); + + // CFI: =1= + // NCFI: =1= + fprintf(stderr, "=1=\n"); + a->f(); // OK + // CFI: =2= + // NCFI: =2= + fprintf(stderr, "=2=\n"); +} +#endif diff --git a/src/compiler-rt/test/cfi/lit.cfg b/src/compiler-rt/test/cfi/lit.cfg index a9b8992ea1..687c80f4f0 100644 --- a/src/compiler-rt/test/cfi/lit.cfg +++ b/src/compiler-rt/test/cfi/lit.cfg @@ -10,8 +10,11 @@ clangxx = ' '.join([config.clang] + config.cxx_mode_flags) config.substitutions.append((r"%clangxx ", clangxx + ' ')) if config.lto_supported: clangxx_cfi = ' '.join(config.lto_launch + [clangxx] + config.lto_flags + ['-flto -fsanitize=cfi ']) + clangxx_cfi_diag = clangxx_cfi + '-fno-sanitize-trap=cfi -fsanitize-recover=cfi ' config.substitutions.append((r"%clangxx_cfi ", clangxx_cfi)) - config.substitutions.append((r"%clangxx_cfi_diag ", clangxx_cfi + '-fno-sanitize-trap=cfi -fsanitize-recover=cfi ')) + config.substitutions.append((r"%clangxx_cfi_diag ", clangxx_cfi_diag)) + config.substitutions.append((r"%clangxx_cfi_dso ", clangxx_cfi + '-fsanitize-cfi-cross-dso ')) + config.substitutions.append((r"%clangxx_cfi_dso_diag ", clangxx_cfi_diag + '-fsanitize-cfi-cross-dso ')) else: config.unsupported = True diff --git a/src/compiler-rt/test/lsan/TestCases/cleanup_in_tsd_destructor.cc b/src/compiler-rt/test/lsan/TestCases/cleanup_in_tsd_destructor.c similarity index 97% rename from src/compiler-rt/test/lsan/TestCases/cleanup_in_tsd_destructor.cc rename to src/compiler-rt/test/lsan/TestCases/cleanup_in_tsd_destructor.c index 5335454ffb..debf05c204 100644 --- a/src/compiler-rt/test/lsan/TestCases/cleanup_in_tsd_destructor.cc +++ b/src/compiler-rt/test/lsan/TestCases/cleanup_in_tsd_destructor.c @@ -4,7 +4,7 @@ // additional cleanup tasks). LSan doesn't actually meet that goal 100%, but it // makes its best effort. // RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0" -// RUN: %clangxx_lsan %s -o %t +// RUN: %clang_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE:use_tls=1 %run %t // RUN: LSAN_OPTIONS=$LSAN_BASE:use_tls=0 not %run %t 2>&1 | FileCheck %s diff --git a/src/compiler-rt/test/lsan/TestCases/disabler.c b/src/compiler-rt/test/lsan/TestCases/disabler.c new file mode 100644 index 0000000000..1c4529df4f --- /dev/null +++ b/src/compiler-rt/test/lsan/TestCases/disabler.c @@ -0,0 +1,24 @@ +// Test for __lsan_disable() / __lsan_enable(). +// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=0" +// RUN: %clang_lsan %s -o %t +// RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t 2>&1 | FileCheck %s + +#include +#include + +#include "sanitizer/lsan_interface.h" + +int main() { + void **p; + { + __lsan_disable(); + p = malloc(sizeof(void *)); + __lsan_enable(); + } + *p = malloc(666); + void *q = malloc(1337); + // Break optimization. + fprintf(stderr, "Test alloc: %p.\n", q); + return 0; +} +// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer: 1337 byte(s) leaked in 1 allocation(s) diff --git a/src/compiler-rt/test/lsan/TestCases/disabler.cc b/src/compiler-rt/test/lsan/TestCases/disabler.cc index f83106501f..12e5ffe4d4 100644 --- a/src/compiler-rt/test/lsan/TestCases/disabler.cc +++ b/src/compiler-rt/test/lsan/TestCases/disabler.cc @@ -13,11 +13,13 @@ int main() { { __lsan::ScopedDisabler d; p = new void *; + fprintf(stderr, "Test alloc p: %p.\n", p); } - *reinterpret_cast(p) = malloc(666); + *p = malloc(666); void *q = malloc(1337); - // Break optimization. - fprintf(stderr, "Test alloc: %p.\n", q); + fprintf(stderr, "Test alloc q: %p.\n", q); return 0; } -// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer: 1337 byte(s) leaked in 1 allocation(s) + +// CHECK: Test alloc p: [[ADDR:.*]]. +// CHECK-NOT: [[ADDR]] diff --git a/src/compiler-rt/test/lsan/TestCases/disabler_in_tsd_destructor.cc b/src/compiler-rt/test/lsan/TestCases/disabler_in_tsd_destructor.c similarity index 92% rename from src/compiler-rt/test/lsan/TestCases/disabler_in_tsd_destructor.cc rename to src/compiler-rt/test/lsan/TestCases/disabler_in_tsd_destructor.c index a0012c74dd..982fb899ec 100644 --- a/src/compiler-rt/test/lsan/TestCases/disabler_in_tsd_destructor.cc +++ b/src/compiler-rt/test/lsan/TestCases/disabler_in_tsd_destructor.c @@ -1,6 +1,6 @@ // Regression test. Disabler should not depend on TSD validity. // RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=1" -// RUN: %clangxx_lsan %s -o %t +// RUN: %clang_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE %run %t #include @@ -13,11 +13,12 @@ pthread_key_t key; void key_destructor(void *arg) { - __lsan::ScopedDisabler d; + __lsan_disable(); void *p = malloc(1337); // Break optimization. fprintf(stderr, "Test alloc: %p.\n", p); pthread_setspecific(key, 0); + __lsan_enable(); } void *thread_func(void *arg) { diff --git a/src/compiler-rt/test/lsan/TestCases/ignore_object.cc b/src/compiler-rt/test/lsan/TestCases/ignore_object.c similarity index 90% rename from src/compiler-rt/test/lsan/TestCases/ignore_object.cc rename to src/compiler-rt/test/lsan/TestCases/ignore_object.c index ac69e12a4b..2aa4f14e29 100644 --- a/src/compiler-rt/test/lsan/TestCases/ignore_object.cc +++ b/src/compiler-rt/test/lsan/TestCases/ignore_object.c @@ -1,6 +1,6 @@ // Test for __lsan_ignore_object(). // RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=0" -// RUN: %clangxx_lsan %s -o %t +// RUN: %clang_lsan %s -o %t // RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t 2>&1 | FileCheck %s #include @@ -10,7 +10,7 @@ int main() { // Explicitly ignored object. - void **p = new void *; + void **p = malloc(sizeof(void *)); // Transitively ignored object. *p = malloc(666); // Non-ignored object. diff --git a/src/compiler-rt/test/msan/ctermid.cc b/src/compiler-rt/test/msan/ctermid.cc new file mode 100644 index 0000000000..a2818e6306 --- /dev/null +++ b/src/compiler-rt/test/msan/ctermid.cc @@ -0,0 +1,13 @@ +// RUN: %clangxx_msan -std=c++11 -O0 %s -o %t && %run %t + +#include +#include +#include + +int main(void) { + unsigned char s[L_ctermid + 1]; + char *res = ctermid((char *)s); + if (res) + printf("%zd\n", strlen(res)); + return 0; +} diff --git a/src/compiler-rt/test/msan/dlopen_executable.cc b/src/compiler-rt/test/msan/dlopen_executable.cc new file mode 100644 index 0000000000..ac8a14b940 --- /dev/null +++ b/src/compiler-rt/test/msan/dlopen_executable.cc @@ -0,0 +1,17 @@ +// RUN: %clangxx_msan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +#include +#include +#include + +static int my_global; + +int main(void) { + int *uninit = (int*)malloc(sizeof(int)); + my_global = *uninit; + void *p = dlopen(0, RTLD_NOW); + assert(p && "failed to get handle to executable"); + return my_global; + // CHECK: MemorySanitizer: use-of-uninitialized-value + // CHECK: #0 {{.*}} in main{{.*}}dlopen_executable.cc:[[@LINE-2]] +} diff --git a/src/compiler-rt/test/msan/fork.cc b/src/compiler-rt/test/msan/fork.cc index 78a62d549e..38c3616ec1 100644 --- a/src/compiler-rt/test/msan/fork.cc +++ b/src/compiler-rt/test/msan/fork.cc @@ -4,6 +4,11 @@ // 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 +// +// Big-endian mips64 currently hangs on this test. Mark it unsupported to allow +// llvm-lit to finish. This also marks mips unsupported in most cases but msan +// is already unsupported for 32-bit mips. +// UNSUPPORTED: mips64-supported-target // Fun fact: if test output is redirected to a file (as opposed to // being piped directly to FileCheck), we may lose some "done"s due to diff --git a/src/compiler-rt/test/msan/insertvalue_origin.cc b/src/compiler-rt/test/msan/insertvalue_origin.cc index 96d27f0893..a0c70023f2 100644 --- a/src/compiler-rt/test/msan/insertvalue_origin.cc +++ b/src/compiler-rt/test/msan/insertvalue_origin.cc @@ -4,7 +4,6 @@ // RUN: FileCheck %s < %t.out && FileCheck %s < %t.out // Test origin propagation through insertvalue IR instruction. -// REQUIRES: stable-runtime #include #include diff --git a/src/compiler-rt/test/msan/signal_stress_test.cc b/src/compiler-rt/test/msan/signal_stress_test.cc index d25bf820ff..5bc6f59213 100644 --- a/src/compiler-rt/test/msan/signal_stress_test.cc +++ b/src/compiler-rt/test/msan/signal_stress_test.cc @@ -1,8 +1,5 @@ // RUN: %clangxx_msan -std=c++11 -O0 %s -o %t && %run %t // -// AArch64 lacks var args instrumentation. -// XFAIL: aarch64 - // Test that va_arg shadow from a signal handler does not leak outside. #include diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-shared-lib.c b/src/compiler-rt/test/profile/Inputs/instrprof-shared-lib.c new file mode 100644 index 0000000000..d22b0a54a0 --- /dev/null +++ b/src/compiler-rt/test/profile/Inputs/instrprof-shared-lib.c @@ -0,0 +1,9 @@ +int g1 = 0; +int g2 = 1; + +void foo(int n) { + if (n % 5 == 0) + g1++; + else + g2++; +} diff --git a/src/compiler-rt/test/profile/Inputs/instrprof-shared-main.c b/src/compiler-rt/test/profile/Inputs/instrprof-shared-main.c new file mode 100644 index 0000000000..60da3b42c6 --- /dev/null +++ b/src/compiler-rt/test/profile/Inputs/instrprof-shared-main.c @@ -0,0 +1,13 @@ +extern int g1, g2; +extern void foo(int n); + +int main() { + int i, j; + for (i = 0; i < 1000; i++) + for (j = 0; j < 1000; j++) + foo(i * j); + + if (g2 - g1 == 280001) + return 0; + return 1; +} diff --git a/src/compiler-rt/test/profile/Linux/instrprof-basic.c b/src/compiler-rt/test/profile/Linux/instrprof-basic.c new file mode 100644 index 0000000000..7ae683d9bd --- /dev/null +++ b/src/compiler-rt/test/profile/Linux/instrprof-basic.c @@ -0,0 +1,31 @@ +// RUN: %clang_profgen -fdata-sections -ffunction-sections -fuse-ld=gold -Wl,--gc-sections -o %t -O3 %s +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t +// RUN: llvm-profdata merge -o %t.profdata %t.profraw +// RUN: %clang_profuse=%t.profdata -o - -S -emit-llvm %s | FileCheck %s + +int begin(int i) { + // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD1:[0-9]+]] + if (i) + return 0; + return 1; +} + +int end(int i) { + // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD2:[0-9]+]] + if (i) + return 0; + return 1; +} + +int main(int argc, const char *argv[]) { + begin(0); + end(1); + + // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[PD2:[0-9]+]] + if (argc) + return 0; + return 1; +} + +// CHECK: ![[PD1]] = !{!"branch_weights", i32 1, i32 2} +// CHECK: ![[PD2]] = !{!"branch_weights", i32 2, i32 1} diff --git a/src/compiler-rt/test/profile/Linux/instrprof-dlopen.test b/src/compiler-rt/test/profile/Linux/instrprof-dlopen.test new file mode 100644 index 0000000000..618367c5de --- /dev/null +++ b/src/compiler-rt/test/profile/Linux/instrprof-dlopen.test @@ -0,0 +1,34 @@ +RUN: mkdir -p %t.d +RUN: %clang_profgen -o %t.d/func.shared -fPIC -shared -fdata-sections -ffunction-sections -fuse-ld=gold -Wl,--gc-sections %S/../Inputs/instrprof-dlopen-func.c +RUN: %clang_profgen -o %t.d/func2.shared -fPIC -shared -fdata-sections -ffunction-sections -fuse-ld=gold -Wl,--gc-sections %S/../Inputs/instrprof-dlopen-func2.c +RUN: %clang -o %t-local -fPIC -DDLOPEN_FUNC_DIR=\"%t.d\" -DDLOPEN_FLAGS="RTLD_LAZY | RTLD_LOCAL" %S/../Inputs/instrprof-dlopen-main.c +RUN: %clang -o %t-global -fPIC -DDLOPEN_FUNC_DIR=\"%t.d\" -DDLOPEN_FLAGS="RTLD_LAZY | RTLD_GLOBAL" %S/../Inputs/instrprof-dlopen-main.c + +RUN: %clang -c -o %t.d/main.o %S/../Inputs/instrprof-dlopen-main.c +RUN: %clang_profgen -fdata-sections -ffunction-sections -fuse-ld=gold -Wl,--gc-sections -o %t-static %S/../Inputs/instrprof-dlopen-func.c %S/../Inputs/instrprof-dlopen-func2.c %t.d/main.o + +RUN: env LLVM_PROFILE_FILE=%t-static.profraw %run %t-static +RUN: env LLVM_PROFILE_FILE=%t-local.profraw %run %t-local +RUN: env LLVM_PROFILE_FILE=%t-global.profraw %run %t-global + +RUN: llvm-profdata merge -o %t-static.profdata %t-static.profraw +RUN: llvm-profdata merge -o %t-local.profdata %t-local.profraw +RUN: llvm-profdata merge -o %t-global.profdata %t-global.profraw + +RUN: %clang_profuse=%t-static.profdata -o %t-func.static.ll -S -emit-llvm %S/../Inputs/instrprof-dlopen-func.c +RUN: %clang_profuse=%t-local.profdata -o %t-func.local.ll -S -emit-llvm %S/../Inputs/instrprof-dlopen-func.c +RUN: %clang_profuse=%t-global.profdata -o %t-func.global.ll -S -emit-llvm %S/../Inputs/instrprof-dlopen-func.c +RUN: diff %t-func.static.ll %t-func.local.ll +RUN: diff %t-func.static.ll %t-func.global.ll + +RUN: %clang_profuse=%t-static.profdata -o %t-func2.static.ll -S -emit-llvm %S/../Inputs/instrprof-dlopen-func2.c +RUN: %clang_profuse=%t-local.profdata -o %t-func2.local.ll -S -emit-llvm %S/../Inputs/instrprof-dlopen-func2.c +RUN: %clang_profuse=%t-global.profdata -o %t-func2.global.ll -S -emit-llvm %S/../Inputs/instrprof-dlopen-func2.c +RUN: diff %t-func2.static.ll %t-func2.local.ll +RUN: diff %t-func2.static.ll %t-func2.global.ll + +RUN: %clang_profuse=%t-static.profdata -o %t-main.static.ll -S -emit-llvm %S/../Inputs/instrprof-dlopen-main.c +RUN: %clang_profuse=%t-local.profdata -o %t-main.local.ll -S -emit-llvm %S/../Inputs/instrprof-dlopen-main.c +RUN: %clang_profuse=%t-local.profdata -o %t-main.global.ll -S -emit-llvm %S/../Inputs/instrprof-dlopen-main.c +RUN: diff %t-main.static.ll %t-main.local.ll +RUN: diff %t-main.static.ll %t-main.global.ll diff --git a/src/compiler-rt/test/profile/Linux/instrprof-dynamic-one-shared.test b/src/compiler-rt/test/profile/Linux/instrprof-dynamic-one-shared.test new file mode 100644 index 0000000000..52f40bf9be --- /dev/null +++ b/src/compiler-rt/test/profile/Linux/instrprof-dynamic-one-shared.test @@ -0,0 +1,23 @@ +RUN: mkdir -p %t.d +RUN: %clang_profgen -fdata-sections -ffunction-sections -fuse-ld=gold -Wl,--gc-sections -o %t.d/a.shared -fPIC -shared %S/../Inputs/instrprof-dynamic-a.cpp +RUN: %clang_profgen -fdata-sections -ffunction-sections -fuse-ld=gold -Wl,--gc-sections -o %t-shared -fPIC -rpath %t.d %t.d/a.shared %S/../Inputs/instrprof-dynamic-b.cpp %S/../Inputs/instrprof-dynamic-main.cpp + +RUN: %clang_profgen -fdata-sections -ffunction-sections -fuse-ld=gold -Wl,--gc-sections -o %t-static %S/../Inputs/instrprof-dynamic-a.cpp %S/../Inputs/instrprof-dynamic-b.cpp %S/../Inputs/instrprof-dynamic-main.cpp + +RUN: env LLVM_PROFILE_FILE=%t-static.profraw %run %t-static +RUN: env LLVM_PROFILE_FILE=%t-shared.profraw %run %t-shared + +RUN: llvm-profdata merge -o %t-static.profdata %t-static.profraw +RUN: llvm-profdata merge -o %t-shared.profdata %t-shared.profraw + +RUN: %clang_profuse=%t-static.profdata -o %t-a.static.ll -S -emit-llvm %S/../Inputs/instrprof-dynamic-a.cpp +RUN: %clang_profuse=%t-shared.profdata -o %t-a.shared.ll -S -emit-llvm %S/../Inputs/instrprof-dynamic-a.cpp +RUN: diff %t-a.static.ll %t-a.shared.ll + +RUN: %clang_profuse=%t-static.profdata -o %t-b.static.ll -S -emit-llvm %S/../Inputs/instrprof-dynamic-b.cpp +RUN: %clang_profuse=%t-shared.profdata -o %t-b.shared.ll -S -emit-llvm %S/../Inputs/instrprof-dynamic-b.cpp +RUN: diff %t-b.static.ll %t-b.shared.ll + +RUN: %clang_profuse=%t-static.profdata -o %t-main.static.ll -S -emit-llvm %S/../Inputs/instrprof-dynamic-main.cpp +RUN: %clang_profuse=%t-shared.profdata -o %t-main.shared.ll -S -emit-llvm %S/../Inputs/instrprof-dynamic-main.cpp +RUN: diff %t-main.static.ll %t-main.shared.ll diff --git a/src/compiler-rt/test/profile/Linux/instrprof-dynamic-two-shared.test b/src/compiler-rt/test/profile/Linux/instrprof-dynamic-two-shared.test new file mode 100644 index 0000000000..949914603b --- /dev/null +++ b/src/compiler-rt/test/profile/Linux/instrprof-dynamic-two-shared.test @@ -0,0 +1,24 @@ +RUN: mkdir -p %t.d +RUN: %clang_profgen -fdata-sections -ffunction-sections -fuse-ld=gold -Wl,--gc-sections -o %t.d/a.shared -fPIC -shared %S/../Inputs/instrprof-dynamic-a.cpp +RUN: %clang_profgen -fdata-sections -ffunction-sections -fuse-ld=gold -Wl,--gc-sections -o %t.d/b.shared -fPIC -shared %S/../Inputs/instrprof-dynamic-b.cpp +RUN: %clang_profgen -fdata-sections -ffunction-sections -fuse-ld=gold -Wl,--gc-sections -o %t-shared -fPIC -rpath %t.d %t.d/a.shared %t.d/b.shared %S/../Inputs/instrprof-dynamic-main.cpp + +RUN: %clang_profgen -o %t-static %S/../Inputs/instrprof-dynamic-a.cpp %S/../Inputs/instrprof-dynamic-b.cpp %S/../Inputs/instrprof-dynamic-main.cpp + +RUN: env LLVM_PROFILE_FILE=%t-static.profraw %run %t-static +RUN: env LLVM_PROFILE_FILE=%t-shared.profraw %run %t-shared + +RUN: llvm-profdata merge -o %t-static.profdata %t-static.profraw +RUN: llvm-profdata merge -o %t-shared.profdata %t-shared.profraw + +RUN: %clang_profuse=%t-static.profdata -o %t-a.static.ll -S -emit-llvm %S/../Inputs/instrprof-dynamic-a.cpp +RUN: %clang_profuse=%t-shared.profdata -o %t-a.shared.ll -S -emit-llvm %S/../Inputs/instrprof-dynamic-a.cpp +RUN: diff %t-a.static.ll %t-a.shared.ll + +RUN: %clang_profuse=%t-static.profdata -o %t-b.static.ll -S -emit-llvm %S/../Inputs/instrprof-dynamic-b.cpp +RUN: %clang_profuse=%t-shared.profdata -o %t-b.shared.ll -S -emit-llvm %S/../Inputs/instrprof-dynamic-b.cpp +RUN: diff %t-b.static.ll %t-b.shared.ll + +RUN: %clang_profuse=%t-static.profdata -o %t-main.static.ll -S -emit-llvm %S/../Inputs/instrprof-dynamic-main.cpp +RUN: %clang_profuse=%t-shared.profdata -o %t-main.shared.ll -S -emit-llvm %S/../Inputs/instrprof-dynamic-main.cpp +RUN: diff %t-main.static.ll %t-main.shared.ll diff --git a/src/compiler-rt/test/profile/Linux/lit.local.cfg b/src/compiler-rt/test/profile/Linux/lit.local.cfg new file mode 100644 index 0000000000..c8c79fc7d8 --- /dev/null +++ b/src/compiler-rt/test/profile/Linux/lit.local.cfg @@ -0,0 +1,37 @@ +import subprocess + +def getRoot(config): + if not config.parent: + return config + return getRoot(config.parent) + + +def is_gold_linker_available(): + + if not config.gold_executable: + return False + try: + ld_cmd = subprocess.Popen([config.gold_executable, '--help'], stdout = subprocess.PIPE) + ld_out = ld_cmd.stdout.read().decode() + ld_cmd.wait() + except: + return False + + if not '-plugin' in ld_out: + return False + + clang_cmd = subprocess.Popen([config.clang, '-fuse-ld=gold', '-xc', '-'], + stdin = subprocess.PIPE, + stdout = subprocess.PIPE, + stderr = subprocess.PIPE) + clang_err = clang_cmd.communicate('int main() { return 0; }')[1] + + if not 'invalid linker' in clang_err: + return True + + return False + +root = getRoot(config) + +if root.host_os not in ['Linux'] or not is_gold_linker_available(): + config.unsupported = True diff --git a/src/compiler-rt/test/profile/instrprof-bufferio.c b/src/compiler-rt/test/profile/instrprof-bufferio.c new file mode 100644 index 0000000000..eed548fd0d --- /dev/null +++ b/src/compiler-rt/test/profile/instrprof-bufferio.c @@ -0,0 +1,128 @@ +// RUN: %clang_profgen -O3 -o %t %s +// RUN: %run %t %t.out.1 %t.out.2 %t.out.3 %t.out.4 +// RUN: cat %t.out.1 | FileCheck %s +// RUN: diff %t.out.1 %t.out.2 +// RUN: diff %t.out.2 %t.out.3 +// RUN: diff %t.out.3 %t.out.4 + +#include +#include +#include +#include + +typedef struct ProfBufferIO ProfBufferIO; +ProfBufferIO *llvmCreateBufferIOInternal(FILE *File, uint32_t DefaultBufferSz); +void llvmDeleteBufferIO(ProfBufferIO *BufferIO); + +int llvmBufferIOWrite(ProfBufferIO *BufferIO, const char *Data, uint32_t Size); +int llvmBufferIOFlush(ProfBufferIO *BufferIO); + +int __llvm_profile_runtime = 0; + +const char *SmallData = "ABC\n"; +const char *MediumData = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"; +char LargeData[10 * 1024]; +int main(int argc, const char *argv[]) { + ProfBufferIO *BufferIO; + FILE *File[4]; + uint32_t IOBufferSize[4] = {8, 128, 8 * 1024, 11 * 1024}; + int I, J; + if (argc < 5) + return 1; + + for (I = 0; I < 10 * 1024 - 2; I++) + LargeData[I] = 'A'; + + LargeData[I++] = '\n'; + LargeData[I++] = '\0'; + + for (J = 0; J < 4; J++) { + File[J] = fopen(argv[1 + J], "w"); + if (!File[J]) + return 1; + + BufferIO = llvmCreateBufferIOInternal(File[J], IOBufferSize[J]); + + llvmBufferIOWrite(BufferIO, "Short Strings:\n", strlen("Short Strings:\n")); + for (I = 0; I < 1024; I++) { + llvmBufferIOWrite(BufferIO, SmallData, strlen(SmallData)); + } + llvmBufferIOWrite(BufferIO, "Long Strings:\n", strlen("Long Strings:\n")); + for (I = 0; I < 1024; I++) { + llvmBufferIOWrite(BufferIO, MediumData, strlen(MediumData)); + } + llvmBufferIOWrite(BufferIO, "Extra Long Strings:\n", + strlen("Extra Long Strings:\n")); + for (I = 0; I < 10; I++) { + llvmBufferIOWrite(BufferIO, LargeData, strlen(LargeData)); + } + llvmBufferIOWrite(BufferIO, "Mixed Strings:\n", strlen("Mixed Strings:\n")); + for (I = 0; I < 1024; I++) { + llvmBufferIOWrite(BufferIO, MediumData, strlen(MediumData)); + llvmBufferIOWrite(BufferIO, SmallData, strlen(SmallData)); + } + llvmBufferIOWrite(BufferIO, "Endings:\n", strlen("Endings:\n")); + llvmBufferIOWrite(BufferIO, "END\n", strlen("END\n")); + llvmBufferIOWrite(BufferIO, "ENDEND\n", strlen("ENDEND\n")); + llvmBufferIOWrite(BufferIO, "ENDENDEND\n", strlen("ENDENDEND\n")); + llvmBufferIOWrite(BufferIO, "ENDENDENDEND\n", strlen("ENDENDENDEND\n")); + llvmBufferIOFlush(BufferIO); + + llvmDeleteBufferIO(BufferIO); + + fclose(File[J]); + } + return 0; +} + +// CHECK-LABEL: Short Strings: +// CHECK: ABC +// CHECK-NEXT: ABC +// CHECK-NEXT: ABC +// CHECK-NEXT: ABC +// CHECK-NEXT: ABC +// CHECK-NEXT: ABC +// CHECK-NEXT: ABC +// CHECK-NEXT: ABC +// CHECK-NEXT: ABC +// CHECK-NEXT: ABC +// CHECK-NEXT: ABC +// CHECK-NEXT: ABC +// CHECK-NEXT: ABC +// CHECK-NEXT: ABC +// CHECK-LABEL: Long Strings: +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-LABEL: Mixed Strings: +// CHECK: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABC +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABC +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABC +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABC +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABC +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABC +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABC +// CHECK-NEXT: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +// CHECK-NEXT: ABC +// CHECK-LABEL: Endings: +// CHECK: END +// CHECK-NEXT: ENDEND +// CHECK-NEXT: ENDENDEND +// CHECK-NEXT: ENDENDENDEND diff --git a/src/compiler-rt/test/profile/instrprof-error.c b/src/compiler-rt/test/profile/instrprof-error.c new file mode 100644 index 0000000000..4386d53218 --- /dev/null +++ b/src/compiler-rt/test/profile/instrprof-error.c @@ -0,0 +1,12 @@ +// RUN: %clang_profgen -o %t -O3 %s +// RUN: touch %t.profraw +// RUN: chmod -w %t.profraw +// RUN: LLVM_PROFILE_FILE=%t.profraw LLVM_PROFILE_VERBOSE_ERRORS=1 %run %t 1 2>&1 | FileCheck %s +// RUN: chmod +w %t.profraw + +int main(int argc, const char *argv[]) { + if (argc < 2) + return 1; + return 0; +} +// CHECK: LLVM Profile: Failed to write file diff --git a/src/compiler-rt/test/profile/instrprof-shared.test b/src/compiler-rt/test/profile/instrprof-shared.test new file mode 100644 index 0000000000..b3f0b9ab4b --- /dev/null +++ b/src/compiler-rt/test/profile/instrprof-shared.test @@ -0,0 +1,75 @@ +""" +This test produces three shared libraries: + +1. libt-instr.so is instrumented +2. libt-no-instr1.so is not instrumented +3. libt-no-instr2.so is built with profile rt linked in (via -u), but the object file is built + with instrumentation turned off. + +After the libraries are built, the main program is then built with/without instrumentation and linked +against 3 libraries above. + +The test is to verify that programs linked against these shared objects with and without instrumentation +enabled behave as expected. +""" + +RUN: mkdir -p %t.d +RUN: %clang_profgen -o %t.d/libt-instr.so -fPIC -shared %S/Inputs/instrprof-shared-lib.c +RUN: %clang -o %t.d/libt-no-instr1.so -fPIC -shared %S/Inputs/instrprof-shared-lib.c +RUN: %clang -c -o %t.d/instrprof-shared-lib-no-instr2.o -fPIC %S/Inputs/instrprof-shared-lib.c +RUN: %clang_profgen -o %t.d/libt-no-instr2.so -fPIC -shared %t.d/instrprof-shared-lib-no-instr2.o + +RUN: %clang_profgen -o %t-instr-instr -L%t.d -rpath %t.d -lt-instr %S/Inputs/instrprof-shared-main.c +RUN: %clang_profgen -o %t-instr-no-instr1 -L%t.d -rpath %t.d -lt-no-instr1 %S/Inputs/instrprof-shared-main.c +RUN: %clang_profgen -o %t-instr-no-instr2 -L%t.d -rpath %t.d -lt-no-instr2 %S/Inputs/instrprof-shared-main.c +RUN: %clang -o %t-no-instr1-instr -L%t.d -rpath %t.d -lt-instr %S/Inputs/instrprof-shared-main.c +RUN: %clang -o %t-no-instr1-no-instr1 -L%t.d -rpath %t.d -lt-no-instr1 %S/Inputs/instrprof-shared-main.c +RUN: %clang -o %t-no-instr1-no-instr2 -L%t.d -rpath %t.d -lt-no-instr2 %S/Inputs/instrprof-shared-main.c +RUN: %clang -c -o %t.d/instrprof-shared-main-no-instr2.o %S/Inputs/instrprof-shared-main.c +RUN: %clang -o %t-no-instr2-instr -L%t.d -rpath %t.d -lt-instr %t.d/instrprof-shared-main-no-instr2.o +RUN: %clang -o %t-no-instr2-no-instr1 -L%t.d -rpath %t.d -lt-no-instr1 %t.d/instrprof-shared-main-no-instr2.o +RUN: %clang -o %t-no-instr2-no-instr2 -L%t.d -rpath %t.d -lt-no-instr2 %t.d/instrprof-shared-main-no-instr2.o + +RUN: env LLVM_PROFILE_FILE=%t-instr-instr.profraw %run %t-instr-instr +RUN: env LLVM_PROFILE_FILE=%t-instr-no-instr1.profraw %run %t-instr-no-instr1 +RUN: env LLVM_PROFILE_FILE=%t-instr-no-instr2.profraw %run %t-instr-no-instr2 +RUN: env LLVM_PROFILE_FILE=%t-no-instr1-instr.profraw %run %t-no-instr1-instr +RUN: env LLVM_PROFILE_FILE=%t-no-instr2-instr.profraw %run %t-no-instr2-instr +RUN: env LLVM_PROFILE_FILE=%t-no-instr1-no-instr1.profraw %run %t-no-instr1-no-instr1 +RUN: env LLVM_PROFILE_FILE=%t-no-instr1-no-instr2.profraw %run %t-no-instr1-no-instr2 +RUN: env LLVM_PROFILE_FILE=%t-no-instr2-no-instr1.profraw %run %t-no-instr2-no-instr1 +RUN: env LLVM_PROFILE_FILE=%t-no-instr2-no-instr2.profraw %run %t-no-instr2-no-instr2 + +RUN: llvm-profdata merge -o %t-instr-instr.profdata %t-instr-instr.profraw +RUN: llvm-profdata merge -o %t-instr-no-instr1.profdata %t-instr-no-instr1.profraw +RUN: llvm-profdata merge -o %t-instr-no-instr2.profdata %t-instr-no-instr2.profraw +RUN: llvm-profdata merge -o %t-no-instr1-instr.profdata %t-no-instr1-instr.profraw +RUN: llvm-profdata merge -o %t-no-instr2-instr.profdata %t-no-instr2-instr.profraw + +RUN: not llvm-profdata merge -o %t-no-instr1-no-instr1.profdata %t-no-instr1-no-instr1.profraw 2>&1 | FileCheck %s --check-prefix=MISSING-FILE +RUN: not llvm-profdata merge -o %t-no-instr2-no-instr1.profdata %t-no-instr2-no-instr1.profraw 2>&1 | FileCheck %s --check-prefix=MISSING-FILE +MISSING-FILE: profraw + +RUN: llvm-profdata show -counts --function main %t-instr-instr.profdata | grep -v 'Total\|Maximum' > %t-main-1 +RUN: llvm-profdata show -counts --function main %t-instr-no-instr1.profdata | grep -v 'Total\|Maximum' > %t-main-2 +RUN: llvm-profdata show -counts --function main %t-instr-no-instr2.profdata | grep -v 'Total\|Maximum' > %t-main-3 +RUN: llvm-profdata show -counts --function foo %t-instr-instr.profdata | grep -v 'Total\|Maximum' > %t-foo-1 +RUN: llvm-profdata show -counts --function foo %t-no-instr1-instr.profdata | grep -v 'Total\|Maximum' > %t-foo-2 +RUN: llvm-profdata show -counts --function foo %t-no-instr2-instr.profdata | grep -v 'Total\|Maximum' > %t-foo-3 + +RUN: %clang_profuse=%t-instr-instr.profdata -o %t-main-instr-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-main.c +RUN: %clang_profuse=%t-instr-no-instr1.profdata -o %t-main-instr-no-instr1.ll -S -emit-llvm %S/Inputs/instrprof-shared-main.c +RUN: %clang_profuse=%t-instr-no-instr2.profdata -o %t-main-instr-no-instr2.ll -S -emit-llvm %S/Inputs/instrprof-shared-main.c +RUN: %clang_profuse=%t-instr-instr.profdata -o %t-lib-instr-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-lib.c +RUN: %clang_profuse=%t-no-instr1-instr.profdata -o %t-lib-no-instr1-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-lib.c +RUN: %clang_profuse=%t-no-instr2-instr.profdata -o %t-lib-no-instr2-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-lib.c +RUN: %clang_profuse=%t-instr-instr.profdata -o %t-lib-instr-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-lib.c + +RUN: diff %t-main-instr-no-instr1.ll %t-main-instr-no-instr2.ll +RUN: diff %t-lib-no-instr1-instr.ll %t-lib-no-instr2-instr.ll + +RUN: diff %t-main-1 %t-main-2 +RUN: diff %t-main-1 %t-main-3 +RUN: diff %t-foo-1 %t-foo-2 +RUN: diff %t-foo-1 %t-foo-3 + diff --git a/src/compiler-rt/test/profile/instrprof-value-prof-2.c b/src/compiler-rt/test/profile/instrprof-value-prof-2.c new file mode 100644 index 0000000000..989353e1f5 --- /dev/null +++ b/src/compiler-rt/test/profile/instrprof-value-prof-2.c @@ -0,0 +1,135 @@ +// RUN: %clang_profgen -O2 -o %t %s +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t +// RUN: llvm-profdata merge -o %t.profdata %t.profraw +// RUN: llvm-profdata show --all-functions -ic-targets %t.profdata | FileCheck %s + +#include +#include +#include +typedef struct __llvm_profile_data __llvm_profile_data; +const __llvm_profile_data *__llvm_profile_begin_data(void); +const __llvm_profile_data *__llvm_profile_end_data(void); +void __llvm_profile_set_num_value_sites(__llvm_profile_data *Data, + uint32_t ValueKind, + uint16_t NumValueSites); +__llvm_profile_data * +__llvm_profile_iterate_data(const __llvm_profile_data *Data); +void *__llvm_get_function_addr(const __llvm_profile_data *Data); +void __llvm_profile_instrument_target(uint64_t TargetValue, void *Data, + uint32_t CounterIndex); +void callee1() {} +void callee2() {} + +void caller_without_value_site1() {} +void caller_with_value_site_never_called1() {} +void caller_with_vp1() {} +void caller_with_value_site_never_called2() {} +void caller_without_value_site2() {} +void caller_with_vp2() {} + +int main(int argc, const char *argv[]) { + unsigned S, NS = 10, V; + const __llvm_profile_data *Data, *DataEnd; + + Data = __llvm_profile_begin_data(); + DataEnd = __llvm_profile_end_data(); + for (; Data < DataEnd; Data = __llvm_profile_iterate_data(Data)) { + void *func = __llvm_get_function_addr(Data); + if (func == caller_without_value_site1 || + func == caller_without_value_site2 || + func == callee1 || func == callee2 || func == main) + continue; + + __llvm_profile_set_num_value_sites((__llvm_profile_data *)Data, + 0 /*IPVK_IndirectCallTarget */, 10); + + if (func == caller_with_value_site_never_called1 || + func == caller_with_value_site_never_called2) + continue; + for (S = 0; S < NS; S++) { + unsigned C; + for (C = 0; C < S + 1; C++) { + __llvm_profile_instrument_target((uint64_t)&callee1, (void *)Data, S); + if (C % 2 == 0) + __llvm_profile_instrument_target((uint64_t)&callee2, (void *)Data, S); + } + } + } +} + +// CHECK-LABEL: caller_with_value_site_never_called2: +// CHECK-NEXT: Hash: 0x0000000000000000 +// CHECK-NEXT: Counters: +// CHECK-NEXT: Function count +// CHECK-NEXT: Indirect Call Site Count: 10 +// CHECK-NEXT: Indirect Target Results: +// CHECK-LABEL: caller_with_vp2: +// CHECK-NEXT: Hash: 0x0000000000000000 +// CHECK-NEXT: Counters: +// CHECK-NEXT: Function count: +// CHECK-NEXT: Indirect Call Site Count: 10 +// CHECK-NEXT: Indirect Target Results: +// CHECK-NEXT: [ 0, callee1, 1 ] +// CHECK-NEXT: [ 0, callee2, 1 ] +// CHECK-NEXT: [ 1, callee1, 2 ] +// CHECK-NEXT: [ 1, callee2, 1 ] +// CHECK-NEXT: [ 2, callee1, 3 ] +// CHECK-NEXT: [ 2, callee2, 2 ] +// CHECK-NEXT: [ 3, callee1, 4 ] +// CHECK-NEXT: [ 3, callee2, 2 ] +// CHECK-NEXT: [ 4, callee1, 5 ] +// CHECK-NEXT: [ 4, callee2, 3 ] +// CHECK-NEXT: [ 5, callee1, 6 ] +// CHECK-NEXT: [ 5, callee2, 3 ] +// CHECK-NEXT: [ 6, callee1, 7 ] +// CHECK-NEXT: [ 6, callee2, 4 ] +// CHECK-NEXT: [ 7, callee1, 8 ] +// CHECK-NEXT: [ 7, callee2, 4 ] +// CHECK-NEXT: [ 8, callee1, 9 ] +// CHECK-NEXT: [ 8, callee2, 5 ] +// CHECK-NEXT: [ 9, callee1, 10 ] +// CHECK-NEXT: [ 9, callee2, 5 ] +// CHECK-LABEL: caller_with_vp1: +// CHECK-NEXT: Hash: 0x0000000000000000 +// CHECK-NEXT: Counters: +// CHECK-NEXT: Function count +// CHECK-NEXT: Indirect Call Site Count: 10 +// CHECK-NEXT: Indirect Target Results: +// CHECK-NEXT: [ 0, callee1, 1 ] +// CHECK-NEXT: [ 0, callee2, 1 ] +// CHECK-NEXT: [ 1, callee1, 2 ] +// CHECK-NEXT: [ 1, callee2, 1 ] +// CHECK-NEXT: [ 2, callee1, 3 ] +// CHECK-NEXT: [ 2, callee2, 2 ] +// CHECK-NEXT: [ 3, callee1, 4 ] +// CHECK-NEXT: [ 3, callee2, 2 ] +// CHECK-NEXT: [ 4, callee1, 5 ] +// CHECK-NEXT: [ 4, callee2, 3 ] +// CHECK-NEXT: [ 5, callee1, 6 ] +// CHECK-NEXT: [ 5, callee2, 3 ] +// CHECK-NEXT: [ 6, callee1, 7 ] +// CHECK-NEXT: [ 6, callee2, 4 ] +// CHECK-NEXT: [ 7, callee1, 8 ] +// CHECK-NEXT: [ 7, callee2, 4 ] +// CHECK-NEXT: [ 8, callee1, 9 ] +// CHECK-NEXT: [ 8, callee2, 5 ] +// CHECK-NEXT: [ 9, callee1, 10 ] +// CHECK-NEXT: [ 9, callee2, 5 ] +// CHECK-LABEL: caller_with_value_site_never_called1: +// CHECK-NEXT: Hash: 0x0000000000000000 +// CHECK-NEXT: Counters: +// CHECK-NEXT: Function count: +// CHECK-NEXT: Indirect Call Site Count: 10 +// CHECK-NEXT: Indirect Target Results: +// CHECK-LABEL: caller_without_value_site2: +// CHECK-NEXT: Hash: 0x0000000000000000 +// CHECK-NEXT: Counters: +// CHECK-NEXT: Function count: +// CHECK-NEXT: Indirect Call Site Count: 0 +// CHECK-NEXT: Indirect Target Results: +// CHECK-LABEL: caller_without_value_site1: +// CHECK-NEXT: Hash: 0x0000000000000000 +// CHECK-NEXT: Counters: +// CHECK-NEXT: Function count: +// CHECK-NEXT: Indirect Call Site Count: 0 +// CHECK-NEXT: Indirect Target Results: diff --git a/src/compiler-rt/test/profile/instrprof-value-prof.c b/src/compiler-rt/test/profile/instrprof-value-prof.c new file mode 100644 index 0000000000..f09e1ac432 --- /dev/null +++ b/src/compiler-rt/test/profile/instrprof-value-prof.c @@ -0,0 +1,225 @@ +// RUN: %clang_profgen -O2 -o %t %s +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t 1 +// RUN: env LLVM_PROFILE_FILE=%t-2.profraw %run %t +// RUN: llvm-profdata merge -o %t.profdata %t.profraw +// RUN: llvm-profdata merge -o %t-2.profdata %t-2.profraw +// RUN: llvm-profdata merge -o %t-merged.profdata %t.profraw %t-2.profdata +// RUN: llvm-profdata show --all-functions -ic-targets %t-2.profdata | FileCheck %s -check-prefix=NO-VALUE +// RUN: llvm-profdata show --all-functions -ic-targets %t.profdata | FileCheck %s +// RUN: llvm-profdata show --all-functions -ic-targets %t-merged.profdata | FileCheck %s +// +// RUN: env LLVM_PROFILE_FILE=%t-3.profraw LLVM_VP_BUFFER_SIZE=1 %run %t 1 +// RUN: env LLVM_PROFILE_FILE=%t-4.profraw LLVM_VP_BUFFER_SIZE=8 %run %t 1 +// RUN: env LLVM_PROFILE_FILE=%t-5.profraw LLVM_VP_BUFFER_SIZE=128 %run %t 1 +// RUN: env LLVM_PROFILE_FILE=%t-6.profraw LLVM_VP_BUFFER_SIZE=1024 %run %t 1 +// RUN: env LLVM_PROFILE_FILE=%t-7.profraw LLVM_VP_BUFFER_SIZE=102400 %run %t 1 +// RUN: llvm-profdata merge -o %t-3.profdata %t-3.profraw +// RUN: llvm-profdata merge -o %t-4.profdata %t-4.profraw +// RUN: llvm-profdata merge -o %t-5.profdata %t-5.profraw +// RUN: llvm-profdata merge -o %t-6.profdata %t-6.profraw +// RUN: llvm-profdata merge -o %t-7.profdata %t-7.profraw +// RUN: llvm-profdata show --all-functions -ic-targets %t-3.profdata | FileCheck %s +// RUN: llvm-profdata show --all-functions -ic-targets %t-4.profdata | FileCheck %s +// RUN: llvm-profdata show --all-functions -ic-targets %t-5.profdata | FileCheck %s +// RUN: llvm-profdata show --all-functions -ic-targets %t-6.profdata | FileCheck %s +// RUN: llvm-profdata show --all-functions -ic-targets %t-7.profdata | FileCheck %s + +#include +#include +#include +typedef struct __llvm_profile_data __llvm_profile_data; +const __llvm_profile_data *__llvm_profile_begin_data(void); +const __llvm_profile_data *__llvm_profile_end_data(void); +void __llvm_profile_set_num_value_sites(__llvm_profile_data *Data, + uint32_t ValueKind, + uint16_t NumValueSites); +__llvm_profile_data * +__llvm_profile_iterate_data(const __llvm_profile_data *Data); +void *__llvm_get_function_addr(const __llvm_profile_data *Data); +void __llvm_profile_instrument_target(uint64_t TargetValue, void *Data, + uint32_t CounterIndex); + +#define DEF_FUNC(x) \ + void x() {} +#define DEF_2_FUNCS(x) DEF_FUNC(x##_1) DEF_FUNC(x##_2) +#define DEF_4_FUNCS(x) DEF_2_FUNCS(x##_1) DEF_2_FUNCS(x##_2) +#define DEF_8_FUNCS(x) DEF_4_FUNCS(x##_1) DEF_4_FUNCS(x##_2) +#define DEF_16_FUNCS(x) DEF_8_FUNCS(x##_1) DEF_8_FUNCS(x##_2) +#define DEF_32_FUNCS(x) DEF_16_FUNCS(x##_1) DEF_16_FUNCS(x##_2) +#define DEF_64_FUNCS(x) DEF_32_FUNCS(x##_1) DEF_32_FUNCS(x##_2) +#define DEF_128_FUNCS(x) DEF_64_FUNCS(x##_1) DEF_64_FUNCS(x##_2) + +#define FUNC_ADDR(x) &x, +#define FUNC_2_ADDRS(x) FUNC_ADDR(x##_1) FUNC_ADDR(x##_2) +#define FUNC_4_ADDRS(x) FUNC_2_ADDRS(x##_1) FUNC_2_ADDRS(x##_2) +#define FUNC_8_ADDRS(x) FUNC_4_ADDRS(x##_1) FUNC_4_ADDRS(x##_2) +#define FUNC_16_ADDRS(x) FUNC_8_ADDRS(x##_1) FUNC_8_ADDRS(x##_2) +#define FUNC_32_ADDRS(x) FUNC_16_ADDRS(x##_1) FUNC_16_ADDRS(x##_2) +#define FUNC_64_ADDRS(x) FUNC_32_ADDRS(x##_1) FUNC_32_ADDRS(x##_2) +#define FUNC_128_ADDRS(x) FUNC_64_ADDRS(x##_1) FUNC_64_ADDRS(x##_2) + +DEF_8_FUNCS(callee) +DEF_128_FUNCS(caller) + +void *CallerAddrs[] = {FUNC_128_ADDRS(caller)}; +void *CalleeAddrs[] = {FUNC_8_ADDRS(callee)}; +typedef struct CallerInfo { + void *CallerAddr; + uint32_t NS; /* Number value sites. */ +} CallerInfo; + +CallerInfo CallerInfos[128]; + +int cmpaddr(const void *p1, const void *p2) { + CallerInfo *addr1 = (CallerInfo *)p1; + CallerInfo *addr2 = (CallerInfo *)p2; + return (intptr_t)addr2->CallerAddr - (intptr_t)addr1->CallerAddr; +} + +int main(int argc, const char *argv[]) { + unsigned S, NS = 0, I, V, doInstrument = 1; + const __llvm_profile_data *Data, *DataEnd; + + if (argc < 2) + doInstrument = 0; + + for (I = 0; I < 128; I++) { + CallerInfos[I].CallerAddr = CallerAddrs[I]; + CallerInfos[I].NS = I; + } + qsort(CallerInfos, sizeof(CallerInfos) / sizeof(CallerInfo), sizeof(CallerInfo), + cmpaddr); + + /* We will synthesis value profile data for 128 callers functions. + * The number of * value sites. The number values for each value site + * ranges from 0 to 8. */ + + Data = __llvm_profile_begin_data(); + DataEnd = __llvm_profile_end_data(); + + for (; Data < DataEnd; Data = __llvm_profile_iterate_data(Data)) { + void *func = __llvm_get_function_addr(Data); + CallerInfo Key, *Res; + Key.CallerAddr = func; + Res = (CallerInfo *) bsearch(&Key, CallerInfos, sizeof(CallerInfos) / sizeof(CallerInfo), + sizeof(CallerInfo), cmpaddr); + if (Res) { + NS = Res->NS; + __llvm_profile_set_num_value_sites((__llvm_profile_data *)Data, + 0 /*IPVK_IndirectCallTarget */, NS); + if (!doInstrument) { + continue; + } + for (S = 0; S < NS; S++) { + for (V = 0; V < S % 8; V++) { + unsigned C; + for (C = 0; C < V + 1; C++) + __llvm_profile_instrument_target((uint64_t)CalleeAddrs[V], + (void *)Data, S); + } + } + } + } +} + +// NO-VALUE: Indirect Call Site Count: 127 +// NO-VALUE-NEXT: Indirect Target Results: +// CHECK-LABEL: caller_1_1_1_1_2_2_1: +// CHECK: Indirect Call Site Count: 6 +// CHECK-NEXT: Indirect Target Results: +// CHECK-NEXT: [ 1, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 2, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 2, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 3, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 3, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 3, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 4, callee_1_2_2, 4 ] +// CHECK-NEXT: [ 4, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 4, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 4, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 5, callee_2_1_1, 5 ] +// CHECK-NEXT: [ 5, callee_1_2_2, 4 ] +// CHECK-NEXT: [ 5, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 5, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 5, callee_1_1_1, 1 ] +// CHECK-LABEL: caller_2_2_2_2_2_2_2: +// CHECK: Indirect Call Site Count: 127 +// CHECK-NEXT: Indirect Target Results: +// CHECK-NEXT: [ 1, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 2, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 2, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 3, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 3, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 3, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 4, callee_1_2_2, 4 ] +// CHECK-NEXT: [ 4, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 4, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 4, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 5, callee_2_1_1, 5 ] +// CHECK-NEXT: [ 5, callee_1_2_2, 4 ] +// CHECK-NEXT: [ 5, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 5, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 5, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 6, callee_2_1_2, 6 ] +// CHECK-NEXT: [ 6, callee_2_1_1, 5 ] +// CHECK-NEXT: [ 6, callee_1_2_2, 4 ] +// CHECK-NEXT: [ 6, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 6, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 6, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 7, callee_2_2_1, 7 ] +// CHECK-NEXT: [ 7, callee_2_1_2, 6 ] +// CHECK-NEXT: [ 7, callee_2_1_1, 5 ] +// CHECK-NEXT: [ 7, callee_1_2_2, 4 ] +// CHECK-NEXT: [ 7, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 7, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 7, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 9, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 10, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 10, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 11, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 11, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 11, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 12, callee_1_2_2, 4 ] +// CHECK-NEXT: [ 12, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 12, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 12, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 13, callee_2_1_1, 5 ] +// CHECK-NEXT: [ 13, callee_1_2_2, 4 ] +// CHECK-NEXT: [ 13, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 13, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 13, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 14, callee_2_1_2, 6 ] +// CHECK-NEXT: [ 14, callee_2_1_1, 5 ] +// CHECK-NEXT: [ 14, callee_1_2_2, 4 ] +// CHECK-NEXT: [ 14, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 14, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 14, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 15, callee_2_2_1, 7 ] +// CHECK-NEXT: [ 15, callee_2_1_2, 6 ] +// CHECK-NEXT: [ 15, callee_2_1_1, 5 ] +// CHECK-NEXT: [ 15, callee_1_2_2, 4 ] +// CHECK-NEXT: [ 15, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 15, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 15, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 17, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 18, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 18, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 19, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 19, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 19, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 20, callee_1_2_2, 4 ] +// CHECK-NEXT: [ 20, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 20, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 20, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 21, callee_2_1_1, 5 ] +// CHECK-NEXT: [ 21, callee_1_2_2, 4 ] +// CHECK-NEXT: [ 21, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 21, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 21, callee_1_1_1, 1 ] +// CHECK-NEXT: [ 22, callee_2_1_2, 6 ] +// CHECK-NEXT: [ 22, callee_2_1_1, 5 ] +// CHECK-NEXT: [ 22, callee_1_2_2, 4 ] +// CHECK-NEXT: [ 22, callee_1_2_1, 3 ] +// CHECK-NEXT: [ 22, callee_1_1_2, 2 ] +// CHECK-NEXT: [ 22, callee_1_1_1, 1 ] + diff --git a/src/compiler-rt/test/profile/instrprof-version-mismatch.c b/src/compiler-rt/test/profile/instrprof-version-mismatch.c new file mode 100644 index 0000000000..49ce41177d --- /dev/null +++ b/src/compiler-rt/test/profile/instrprof-version-mismatch.c @@ -0,0 +1,11 @@ +// RUN: %clang_profgen -o %t -O3 %s +// RUN: LLVM_PROFILE_VERBOSE_ERRORS=1 %run %t 1 2>&1 | FileCheck %s + +// override the version variable with a bogus version: +unsigned long long __llvm_profile_raw_version = 10000; +int main(int argc, const char *argv[]) { + if (argc < 2) + return 1; + return 0; +} +// CHECK: LLVM Profile: runtime and instrumentation version mismatch diff --git a/src/compiler-rt/test/profile/instrprof-without-libc.c b/src/compiler-rt/test/profile/instrprof-without-libc.c index fc6c9b25b3..eb0a76ded3 100644 --- a/src/compiler-rt/test/profile/instrprof-without-libc.c +++ b/src/compiler-rt/test/profile/instrprof-without-libc.c @@ -56,5 +56,11 @@ int main(int argc, const char *argv[]) { // CHECK-SYMBOLS-NOT: _fopen // CHECK-SYMBOLS-NOT: _fwrite // CHECK-SYMBOLS-NOT: _getenv +// CHECK-SYMBOLS-NOT: getenv // CHECK-SYMBOLS-NOT: _malloc +// CHECK-SYMBOLS-NOT: malloc +// CHECK-SYMBOLS-NOT: _calloc +// CHECK-SYMBOLS-NOT: calloc +// CHECK-SYMBOLS-NOT: _free +// CHECK-SYMBOLS-NOT: free // CHECK-SYMBOLS-NOT: _open diff --git a/src/compiler-rt/test/safestack/lit.cfg b/src/compiler-rt/test/safestack/lit.cfg index 13fc92fa4b..535c09742c 100644 --- a/src/compiler-rt/test/safestack/lit.cfg +++ b/src/compiler-rt/test/safestack/lit.cfg @@ -22,3 +22,8 @@ if config.lto_supported: # SafeStack tests are currently supported on Linux, FreeBSD and Darwin only. if config.host_os not in ['Linux', 'FreeBSD', 'Darwin']: config.unsupported = True + +# Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL +# because the test fail due some runtime issue. +if config.target_arch != 'aarch64': + config.available_features.add('stable-runtime') diff --git a/src/compiler-rt/test/safestack/overflow.c b/src/compiler-rt/test/safestack/overflow.c index 14e29823cd..62f8653691 100644 --- a/src/compiler-rt/test/safestack/overflow.c +++ b/src/compiler-rt/test/safestack/overflow.c @@ -7,6 +7,8 @@ // Test that buffer overflows on the unsafe stack do not affect variables on the // safe stack. +// REQUIRES: stable-runtime + __attribute__((noinline)) void fct(volatile int *buffer) { @@ -15,9 +17,13 @@ void fct(volatile int *buffer) int main(int argc, char **argv) { + int prebuf[7]; int value1 = 42; int buffer[5]; int value2 = 42; + int postbuf[7]; + fct(prebuf + 1); + fct(postbuf + 1); fct(buffer); return value1 != 42 || value2 != 42; } diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/closedir.c b/src/compiler-rt/test/sanitizer_common/TestCases/Linux/closedir.c new file mode 100644 index 0000000000..990628db40 --- /dev/null +++ b/src/compiler-rt/test/sanitizer_common/TestCases/Linux/closedir.c @@ -0,0 +1,5 @@ +// Check that closedir(NULL) is ok. +// RUN: %clang -O2 %s -o %t && %run %t +#include +#include +int main() { closedir(0); } diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/Linux/ill.cc b/src/compiler-rt/test/sanitizer_common/TestCases/Linux/ill.cc new file mode 100644 index 0000000000..1edad4817a --- /dev/null +++ b/src/compiler-rt/test/sanitizer_common/TestCases/Linux/ill.cc @@ -0,0 +1,27 @@ +// Test the handle_sigill option. +// RUN: %clang %s -o %t -O1 +// RUN: not --crash %run %t 2>&1 | FileCheck --check-prefix=CHECK0 %s +// RUN: %env_tool_opts=handle_sigill=0 not --crash %run %t 2>&1 | FileCheck --check-prefix=CHECK0 %s +// RUN: %env_tool_opts=handle_sigill=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK1 %s +// FIXME: implement in other sanitizers, not just asan. +// XFAIL: msan +// XFAIL: lsan +// XFAIL: tsan +// +// FIXME: seems to fail on ARM +// REQUIRES: x86_64-supported-target +#include +#include +#include + +void death() { + fprintf(stderr, "DEATH CALLBACK\n"); +} + +int main(int argc, char **argv) { + __sanitizer_set_death_callback(death); + __builtin_trap(); +} +// CHECK1: ERROR: {{.*}}Sanitizer: +// CHECK1: DEATH CALLBACK +// CHECK0-NOT: Sanitizer diff --git a/src/compiler-rt/test/sanitizer_common/TestCases/fopen_nullptr.c b/src/compiler-rt/test/sanitizer_common/TestCases/fopen_nullptr.c new file mode 100644 index 0000000000..960dda334a --- /dev/null +++ b/src/compiler-rt/test/sanitizer_common/TestCases/fopen_nullptr.c @@ -0,0 +1,6 @@ +// Check that fopen(NULL, "r") is ok. +// RUN: %clang -O2 %s -o %t && %run %t +#include +const char *fn = NULL; +FILE *f; +int main() { f = fopen(fn, "r"); } diff --git a/src/compiler-rt/test/tsan/CMakeLists.txt b/src/compiler-rt/test/tsan/CMakeLists.txt index 1492ddb64f..a058602659 100644 --- a/src/compiler-rt/test/tsan/CMakeLists.txt +++ b/src/compiler-rt/test/tsan/CMakeLists.txt @@ -1,30 +1,56 @@ set(TSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) -if(NOT ${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "mips" AND NOT APPLE) +if(${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "x86_64") list(APPEND TSAN_TEST_DEPS GotsanRuntimeCheck) endif() if(NOT COMPILER_RT_STANDALONE_BUILD) list(APPEND TSAN_TEST_DEPS tsan) endif() if(COMPILER_RT_HAS_LIBCXX_SOURCES AND - COMPILER_RT_TEST_COMPILER_ID STREQUAL "Clang") + COMPILER_RT_TEST_COMPILER_ID STREQUAL "Clang" + AND NOT APPLE) list(APPEND TSAN_TEST_DEPS libcxx_tsan) set(TSAN_HAS_LIBCXX True) else() set(TSAN_HAS_LIBCXX False) endif() -configure_lit_site_cfg( - ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in - ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg) +set(TSAN_TESTSUITES) + +set(TSAN_TEST_ARCH ${TSAN_SUPPORTED_ARCH}) +if(APPLE) + darwin_filter_host_archs(TSAN_SUPPORTED_ARCH TSAN_TEST_ARCH) +endif() + +foreach(arch ${TSAN_TEST_ARCH}) + string(TOLOWER "-${arch}" TSAN_TEST_CONFIG_SUFFIX) + if(ANDROID OR ${arch} MATCHES "arm|aarch64") + # This is only true if we are cross-compiling. + # Build all tests with host compiler and use host tools. + set(TSAN_TEST_TARGET_CC ${COMPILER_RT_TEST_COMPILER}) + set(TSAN_TEST_TARGET_CFLAGS ${COMPILER_RT_TEST_COMPILER_CFLAGS}) + else() + get_target_flags_for_arch(${arch} TSAN_TEST_TARGET_CFLAGS) + string(REPLACE ";" " " TSAN_TEST_TARGET_CFLAGS "${TSAN_TEST_TARGET_CFLAGS}") + endif() + + string(TOUPPER ${arch} ARCH_UPPER_CASE) + set(CONFIG_NAME ${ARCH_UPPER_CASE}Config) + + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg) + list(APPEND TSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}) +endforeach() if(COMPILER_RT_INCLUDE_TESTS) configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg) list(APPEND TSAN_TEST_DEPS TsanUnitTests) + list(APPEND TSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit) endif() add_lit_testsuite(check-tsan "Running ThreadSanitizer tests" - ${CMAKE_CURRENT_BINARY_DIR} + ${TSAN_TESTSUITES} DEPENDS ${TSAN_TEST_DEPS}) set_target_properties(check-tsan PROPERTIES FOLDER "TSan tests") diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-async-norace.mm b/src/compiler-rt/test/tsan/Darwin/gcd-async-norace.mm new file mode 100644 index 0000000000..b987e00656 --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/gcd-async-norace.mm @@ -0,0 +1,26 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import + +long global; + +int main() { + NSLog(@"Hello world."); + + global = 42; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + global = 43; + + dispatch_sync(dispatch_get_main_queue(), ^{ + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + }); + + CFRunLoopRun(); + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-async-race.mm b/src/compiler-rt/test/tsan/Darwin/gcd-async-race.mm new file mode 100644 index 0000000000..31163f9728 --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/gcd-async-race.mm @@ -0,0 +1,38 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %deflake %run %t 2>&1 + +#import + +#import "../test.h" + +long global; + +int main() { + NSLog(@"Hello world."); + NSLog(@"addr=%p\n", &global); + barrier_init(&barrier, 2); + + global = 42; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + global = 43; + barrier_wait(&barrier); + }); + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + barrier_wait(&barrier); + global = 44; + + dispatch_sync(dispatch_get_main_queue(), ^{ + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + }); + + CFRunLoopRun(); + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: addr=[[ADDR:0x[0-9,a-f]+]] +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Location is global 'global' at [[ADDR]] (global_race.cc.exe+0x{{[0-9,a-f]+}}) +// CHECK: Done. diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-groups-norace.mm b/src/compiler-rt/test/tsan/Darwin/gcd-groups-norace.mm new file mode 100644 index 0000000000..fb4d804ed8 --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/gcd-groups-norace.mm @@ -0,0 +1,53 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import + +#import "../test.h" + +long global; + +int main() { + NSLog(@"Hello world."); + NSLog(@"addr=%p\n", &global); + + dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + global = 42; + + dispatch_group_t g = dispatch_group_create(); + dispatch_group_async(g, q, ^{ + global = 43; + }); + dispatch_group_wait(g, DISPATCH_TIME_FOREVER); + + global = 44; + + dispatch_group_enter(g); + dispatch_async(q, ^{ + global = 45; + dispatch_group_leave(g); + }); + dispatch_group_wait(g, DISPATCH_TIME_FOREVER); + + global = 46; + + dispatch_group_enter(g); + dispatch_async(q, ^{ + global = 47; + dispatch_group_leave(g); + }); + dispatch_group_notify(g, q, ^{ + global = 48; + + dispatch_sync(dispatch_get_main_queue(), ^{ + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + }); + + CFRunLoopRun(); + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-groups-stress.mm b/src/compiler-rt/test/tsan/Darwin/gcd-groups-stress.mm new file mode 100644 index 0000000000..62a80085ed --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/gcd-groups-stress.mm @@ -0,0 +1,43 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import + +void notify_callback(void *context) { + // Do nothing. +} + +int main() { + NSLog(@"Hello world."); + + dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + for (int i = 0; i < 300000; i++) { + dispatch_group_t g = dispatch_group_create(); + dispatch_group_enter(g); + dispatch_async(q, ^{ + dispatch_group_leave(g); + }); + dispatch_group_notify(g, q, ^{ + // Do nothing. + }); + dispatch_release(g); + } + + for (int i = 0; i < 300000; i++) { + dispatch_group_t g = dispatch_group_create(); + dispatch_group_enter(g); + dispatch_async(q, ^{ + dispatch_group_leave(g); + }); + dispatch_group_notify_f(g, q, nullptr, ¬ify_callback); + dispatch_release(g); + } + + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer +// CHECK-NOT: CHECK failed diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-once.mm b/src/compiler-rt/test/tsan/Darwin/gcd-once.mm new file mode 100644 index 0000000000..17757d2037 --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/gcd-once.mm @@ -0,0 +1,55 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import + +#import "../test.h" + +static const long kNumThreads = 4; + +long global; +long global2; + +static dispatch_once_t once_token; +static dispatch_once_t once_token2; + +void f(void *) { + global2 = 42; + usleep(100000); +} + +void *Thread(void *a) { + barrier_wait(&barrier); + + dispatch_once(&once_token, ^{ + global = 42; + usleep(100000); + }); + long x = global; + + dispatch_once_f(&once_token2, NULL, f); + long x2 = global2; + + fprintf(stderr, "global = %ld\n", x); + fprintf(stderr, "global2 = %ld\n", x2); + return 0; +} + +int main() { + fprintf(stderr, "Hello world.\n"); + barrier_init(&barrier, kNumThreads); + + pthread_t t[kNumThreads]; + for (int i = 0; i < kNumThreads; i++) { + pthread_create(&t[i], 0, Thread, 0); + } + for (int i = 0; i < kNumThreads; i++) { + pthread_join(t[i], 0); + } + + fprintf(stderr, "Done.\n"); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-semaphore-norace.mm b/src/compiler-rt/test/tsan/Darwin/gcd-semaphore-norace.mm new file mode 100644 index 0000000000..cd52a79ca6 --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/gcd-semaphore-norace.mm @@ -0,0 +1,29 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import + +long global; + +int main() { + NSLog(@"Hello world."); + + global = 42; + + dispatch_semaphore_t sem = dispatch_semaphore_create(0); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + global = 43; + dispatch_semaphore_signal(sem); + }); + + dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); + global = 44; + + NSLog(@"Done."); + return 0; +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-serial-queue-norace.mm b/src/compiler-rt/test/tsan/Darwin/gcd-serial-queue-norace.mm new file mode 100644 index 0000000000..8f6de27695 --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/gcd-serial-queue-norace.mm @@ -0,0 +1,40 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import + +#import "../test.h" + +long global; + +int main() { + NSLog(@"Hello world."); + NSLog(@"addr=%p\n", &global); + + dispatch_queue_t q1 = dispatch_queue_create("my.queue1", DISPATCH_QUEUE_CONCURRENT); + dispatch_queue_t q2 = dispatch_queue_create("my.queue2", DISPATCH_QUEUE_SERIAL); + + global = 42; + for (int i = 0; i < 10; i++) { + dispatch_async(q1, ^{ + for (int i = 0; i < 100; i++) { + dispatch_sync(q2, ^{ + global++; + }); + } + }); + } + + dispatch_barrier_async(q1, ^{ + dispatch_sync(dispatch_get_main_queue(), ^{ + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + }); + + CFRunLoopRun(); + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-sync-norace.mm b/src/compiler-rt/test/tsan/Darwin/gcd-sync-norace.mm new file mode 100644 index 0000000000..f21cfdedbc --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/gcd-sync-norace.mm @@ -0,0 +1,32 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import + +long global; + +static const long nIter = 1000; + +int main() { + NSLog(@"Hello world."); + + global = 42; + for (int i = 0; i < nIter; i++) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + dispatch_sync(dispatch_get_main_queue(), ^{ + global = i; + + if (i == nIter - 1) { + CFRunLoopStop(CFRunLoopGetCurrent()); + } + }); + }); + } + + CFRunLoopRun(); + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/src/compiler-rt/test/tsan/Darwin/gcd-sync-race.mm b/src/compiler-rt/test/tsan/Darwin/gcd-sync-race.mm new file mode 100644 index 0000000000..62901d9b26 --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/gcd-sync-race.mm @@ -0,0 +1,44 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %deflake %run %t 2>&1 + +#import + +#import "../test.h" + +long global; + +int main() { + NSLog(@"Hello world."); + NSLog(@"addr=%p\n", &global); + barrier_init(&barrier, 2); + + dispatch_queue_t q1 = dispatch_queue_create("my.queue1", DISPATCH_QUEUE_CONCURRENT); + dispatch_queue_t q2 = dispatch_queue_create("my.queue2", DISPATCH_QUEUE_CONCURRENT); + + global = 42; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + dispatch_sync(q1, ^{ + global = 43; + barrier_wait(&barrier); + }); + }); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + dispatch_sync(q2, ^{ + barrier_wait(&barrier); + global = 44; + + dispatch_sync(dispatch_get_main_queue(), ^{ + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + }); + }); + + CFRunLoopRun(); + NSLog(@"Done."); +} + +// CHECK: Hello world. +// CHECK: addr=[[ADDR:0x[0-9,a-f]+]] +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Location is global 'global' at [[ADDR]] (global_race.cc.exe+0x{{[0-9,a-f]+}}) +// CHECK: Done. diff --git a/src/compiler-rt/test/tsan/Darwin/lit.local.cfg b/src/compiler-rt/test/tsan/Darwin/lit.local.cfg new file mode 100644 index 0000000000..a85dfcd24c --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/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 ['Darwin']: + config.unsupported = True diff --git a/src/compiler-rt/test/tsan/Darwin/objc-race.mm b/src/compiler-rt/test/tsan/Darwin/objc-race.mm new file mode 100644 index 0000000000..bd93d2f1c2 --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/objc-race.mm @@ -0,0 +1,55 @@ +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %deflake %run %t 2>&1 + +#import + +#import "../test.h" + +@interface MyClass : NSObject { + long instance_variable; +} +- (void)method:(long)value; +@end + +@implementation MyClass + +- (void)method:(long)value { + self->instance_variable = value; +} + +@end + +int main() { + NSLog(@"Hello world."); + barrier_init(&barrier, 2); + + MyClass *my_object = [MyClass new]; + [my_object method:42]; + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [my_object method:43]; + barrier_wait(&barrier); + }); + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + barrier_wait(&barrier); + [my_object method:44]; + + dispatch_sync(dispatch_get_main_queue(), ^{ + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + }); + + CFRunLoopRun(); + NSLog(@"Done."); + return 0; +} + +// CHECK: Hello world. +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Write of size 8 +// CHECK: #0 -[MyClass method:] +// CHECK: Write of size 8 +// CHECK: #0 -[MyClass method:] +// CHECK: Location is heap block +// CHECK: Done. diff --git a/src/compiler-rt/test/tsan/Darwin/objc-simple.mm b/src/compiler-rt/test/tsan/Darwin/objc-simple.mm new file mode 100644 index 0000000000..a4bf1f1bea --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/objc-simple.mm @@ -0,0 +1,13 @@ +// Test that a simple Obj-C program runs and exits without any warnings. + +// RUN: %clang_tsan %s -o %t -framework Foundation +// RUN: %run %t 2>&1 + +#import + +int main() { + NSLog(@"Hello world"); +} + +// CHECK: Hello world +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/src/compiler-rt/test/tsan/Darwin/osspinlock-norace.cc b/src/compiler-rt/test/tsan/Darwin/osspinlock-norace.cc new file mode 100644 index 0000000000..2ac3989c22 --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/osspinlock-norace.cc @@ -0,0 +1,30 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +#include +#include +#include + +int Global; +OSSpinLock lock; + +void *Thread(void *x) { + OSSpinLockLock(&lock); + Global++; + OSSpinLockUnlock(&lock); + return NULL; +} + +int main() { + fprintf(stderr, "Hello world.\n"); + + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread, NULL); + pthread_create(&t[1], NULL, Thread, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); + + fprintf(stderr, "Done.\n"); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/src/compiler-rt/test/tsan/Darwin/symbolizer-atos.cc b/src/compiler-rt/test/tsan/Darwin/symbolizer-atos.cc new file mode 100644 index 0000000000..960fecc986 --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/symbolizer-atos.cc @@ -0,0 +1,26 @@ +// RUN: %clangxx_tsan %s -o %t +// RUN: %env_tsan_opts=verbosity=2:external_symbolizer_path=/usr/bin/atos %deflake %run %t | FileCheck %s +#include "../test.h" + +int GlobalData[10]; + +void *Thread(void *a) { + barrier_wait(&barrier); + GlobalData[2] = 42; + return 0; +} + +int main() { + barrier_init(&barrier, 2); + print_address("addr=", 1, GlobalData); + pthread_t t; + pthread_create(&t, 0, Thread, 0); + GlobalData[2] = 43; + barrier_wait(&barrier); + pthread_join(t, 0); +} + +// CHECK: Using atos at user-specified path: /usr/bin/atos +// CHECK: addr=[[ADDR:0x[0-9,a-f]+]] +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Location is global 'GlobalData' at [[ADDR]] ({{.*}}+0x{{[0-9,a-f]+}}) diff --git a/src/compiler-rt/test/tsan/Darwin/symbolizer-dladdr.cc b/src/compiler-rt/test/tsan/Darwin/symbolizer-dladdr.cc new file mode 100644 index 0000000000..3b213dda85 --- /dev/null +++ b/src/compiler-rt/test/tsan/Darwin/symbolizer-dladdr.cc @@ -0,0 +1,27 @@ +// RUN: %clangxx_tsan %s -o %t +// RUN: %env_tsan_opts=verbosity=2:external_symbolizer_path= %deflake %run %t | FileCheck %s +#include "../test.h" + +int GlobalData[10]; + +void *Thread(void *a) { + barrier_wait(&barrier); + GlobalData[2] = 42; + return 0; +} + +int main() { + barrier_init(&barrier, 2); + print_address("addr=", 1, GlobalData); + pthread_t t; + pthread_create(&t, 0, Thread, 0); + GlobalData[2] = 43; + barrier_wait(&barrier); + pthread_join(t, 0); +} + +// CHECK: External symbolizer is explicitly disabled. +// CHECK: Using dladdr symbolizer. +// CHECK: addr=[[ADDR:0x[0-9,a-f]+]] +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Location is global 'GlobalData' at [[ADDR]] ({{.*}}+0x{{[0-9,a-f]+}}) diff --git a/src/compiler-rt/test/tsan/Linux/check_memcpy.cc b/src/compiler-rt/test/tsan/Linux/check_memcpy.cc new file mode 100644 index 0000000000..8ad04c07cf --- /dev/null +++ b/src/compiler-rt/test/tsan/Linux/check_memcpy.cc @@ -0,0 +1,15 @@ +// Test that verifies TSan runtime doesn't contain compiler-emitted +// memcpy/memmove calls. It builds the binary with TSan and passes it to +// check_memcpy.sh script. + +// RUN: %clangxx_tsan -O1 %s -o %t +// RUN: llvm-objdump -d %t | FileCheck %s + +int main() { + return 0; +} + +// CHECK-NOT: callq {{.*<(__interceptor_)?mem(cpy|set)>}} +// tail calls: +// CHECK-NOT: jmpq {{.*<(__interceptor_)?mem(cpy|set)>}} + diff --git a/src/compiler-rt/test/tsan/allocator_returns_null.cc b/src/compiler-rt/test/tsan/allocator_returns_null.cc index cde706bc8a..66930076ac 100644 --- a/src/compiler-rt/test/tsan/allocator_returns_null.cc +++ b/src/compiler-rt/test/tsan/allocator_returns_null.cc @@ -4,11 +4,11 @@ // // RUN: %clangxx_tsan -O0 %s -o %t // RUN: not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH -// RUN: TSAN_OPTIONS=allocator_may_return_null=0 not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH -// RUN: TSAN_OPTIONS=allocator_may_return_null=0 not %run %t calloc 2>&1 | FileCheck %s --check-prefix=CHECK-cCRASH -// RUN: TSAN_OPTIONS=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 | FileCheck %s --check-prefix=CHECK-coCRASH -// RUN: TSAN_OPTIONS=allocator_may_return_null=0 not %run %t realloc 2>&1 | FileCheck %s --check-prefix=CHECK-rCRASH -// RUN: TSAN_OPTIONS=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mrCRASH +// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH +// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 | FileCheck %s --check-prefix=CHECK-cCRASH +// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 | FileCheck %s --check-prefix=CHECK-coCRASH +// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t realloc 2>&1 | FileCheck %s --check-prefix=CHECK-rCRASH +// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mrCRASH #include #include diff --git a/src/compiler-rt/test/tsan/barrier.cc b/src/compiler-rt/test/tsan/barrier.cc index d8c2b6ffe5..de2756de2a 100644 --- a/src/compiler-rt/test/tsan/barrier.cc +++ b/src/compiler-rt/test/tsan/barrier.cc @@ -2,6 +2,9 @@ // CHECK-NOT: ThreadSanitizer: data race // CHECK: DONE +// pthread barriers are not available on OS X +// UNSUPPORTED: darwin + #include #include #include diff --git a/src/compiler-rt/test/tsan/bench_acquire_only.cc b/src/compiler-rt/test/tsan/bench_acquire_only.cc index 5cd6bd74eb..0ed21b4612 100644 --- a/src/compiler-rt/test/tsan/bench_acquire_only.cc +++ b/src/compiler-rt/test/tsan/bench_acquire_only.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" int x; diff --git a/src/compiler-rt/test/tsan/bench_acquire_release.cc b/src/compiler-rt/test/tsan/bench_acquire_release.cc index 9e53a7b26e..3799452a16 100644 --- a/src/compiler-rt/test/tsan/bench_acquire_release.cc +++ b/src/compiler-rt/test/tsan/bench_acquire_release.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" int x; diff --git a/src/compiler-rt/test/tsan/bench_local_mutex.cc b/src/compiler-rt/test/tsan/bench_local_mutex.cc index 0fa1db0c88..15f83bc8b2 100644 --- a/src/compiler-rt/test/tsan/bench_local_mutex.cc +++ b/src/compiler-rt/test/tsan/bench_local_mutex.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" pthread_mutex_t *mtx; diff --git a/src/compiler-rt/test/tsan/bench_mutex.cc b/src/compiler-rt/test/tsan/bench_mutex.cc index 324d53fd7f..58aa86a787 100644 --- a/src/compiler-rt/test/tsan/bench_mutex.cc +++ b/src/compiler-rt/test/tsan/bench_mutex.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" pthread_mutex_t mtx; diff --git a/src/compiler-rt/test/tsan/bench_release_only.cc b/src/compiler-rt/test/tsan/bench_release_only.cc index 0a86f73f24..7f26041afc 100644 --- a/src/compiler-rt/test/tsan/bench_release_only.cc +++ b/src/compiler-rt/test/tsan/bench_release_only.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" int *x; diff --git a/src/compiler-rt/test/tsan/bench_rwmutex.cc b/src/compiler-rt/test/tsan/bench_rwmutex.cc index 818ee8c82b..2b3dcb012e 100644 --- a/src/compiler-rt/test/tsan/bench_rwmutex.cc +++ b/src/compiler-rt/test/tsan/bench_rwmutex.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" pthread_rwlock_t mtx; diff --git a/src/compiler-rt/test/tsan/bench_single_writer.cc b/src/compiler-rt/test/tsan/bench_single_writer.cc index 0d3810a03a..3d2ea150b5 100644 --- a/src/compiler-rt/test/tsan/bench_single_writer.cc +++ b/src/compiler-rt/test/tsan/bench_single_writer.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" int x; diff --git a/src/compiler-rt/test/tsan/bench_ten_mutexes.cc b/src/compiler-rt/test/tsan/bench_ten_mutexes.cc index 876f1365ee..e7fa05ea82 100644 --- a/src/compiler-rt/test/tsan/bench_ten_mutexes.cc +++ b/src/compiler-rt/test/tsan/bench_ten_mutexes.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// bench.h needs pthread barriers which are not available on OS X +// UNSUPPORTED: darwin + #include "bench.h" const int kMutex = 10; diff --git a/src/compiler-rt/test/tsan/cond_cancel.c b/src/compiler-rt/test/tsan/cond_cancel.c index ddfb745174..fb6a66136b 100644 --- a/src/compiler-rt/test/tsan/cond_cancel.c +++ b/src/compiler-rt/test/tsan/cond_cancel.c @@ -1,6 +1,14 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s // CHECK-NOT: WARNING // CHECK: OK +// This test is failing on powerpc64 (VMA=44). After calling pthread_cancel, +// the Thread-specific data destructors are not called, so the destructor +// "thread_finalize" (defined in tsan_interceptors.cc) can not set the status +// of the thread to "ThreadStatusFinished" failing a check in "SetJoined" +// (defined in sanitizer_thread_registry.cc). It might seem a bug on glibc, +// however the same version GLIBC-2.17 will not make fail the test on +// powerpc64 BE (VMA=46) +// XFAIL: powerpc64-unknown-linux-gnu #include "test.h" diff --git a/src/compiler-rt/test/tsan/cond_version.c b/src/compiler-rt/test/tsan/cond_version.c index 2282c3ad73..6bae776e6a 100644 --- a/src/compiler-rt/test/tsan/cond_version.c +++ b/src/compiler-rt/test/tsan/cond_version.c @@ -3,6 +3,9 @@ // previously there were issues with versioned symbols. // CHECK: OK +// OS X doesn't have pthread_condattr_setclock. +// UNSUPPORTED: darwin + #include #include #include diff --git a/src/compiler-rt/test/tsan/deadlock_detector_stress_test.cc b/src/compiler-rt/test/tsan/deadlock_detector_stress_test.cc index efc13ae262..bbaaabbb3c 100644 --- a/src/compiler-rt/test/tsan/deadlock_detector_stress_test.cc +++ b/src/compiler-rt/test/tsan/deadlock_detector_stress_test.cc @@ -1,12 +1,12 @@ // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadMutex -// RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOT-SECOND -// RUN: TSAN_OPTIONS="detect_deadlocks=1 second_deadlock_stack=1" %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SECOND +// RUN: %env_tsan_opts=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOT-SECOND +// RUN: %env_tsan_opts=detect_deadlocks=1:second_deadlock_stack=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SECOND // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadSpinLock -// RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s +// RUN: %env_tsan_opts=detect_deadlocks=1 %deflake %run %t | FileCheck %s // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadRWLock -// RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-RD +// RUN: %env_tsan_opts=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-RD // RUN: %clangxx_tsan %s -o %t -DLockType=PthreadRecursiveMutex -// RUN: TSAN_OPTIONS=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-REC +// RUN: %env_tsan_opts=detect_deadlocks=1 %deflake %run %t | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-REC #include "test.h" #undef NDEBUG #include @@ -56,6 +56,7 @@ class PthreadRecursiveMutex : public PthreadMutex { static bool supports_recursive_lock() { return true; } }; +#ifndef __APPLE__ class PthreadSpinLock { public: PthreadSpinLock() { assert(0 == pthread_spin_init(&mu_, 0)); } @@ -76,6 +77,9 @@ class PthreadSpinLock { pthread_spinlock_t mu_; char padding_[64 - sizeof(pthread_spinlock_t)]; }; +#else +class PthreadSpinLock : public PthreadMutex { }; +#endif class PthreadRWLock { public: @@ -95,7 +99,7 @@ class PthreadRWLock { private: pthread_rwlock_t mu_; - char padding_[64 - sizeof(pthread_rwlock_t)]; + char padding_[256 - sizeof(pthread_rwlock_t)]; }; class LockTest { @@ -148,7 +152,7 @@ class LockTest { fprintf(stderr, "Starting Test1\n"); // CHECK: Starting Test1 Init(5); - fprintf(stderr, "Expecting lock inversion: %p %p\n", A(0), A(1)); + print_address("Expecting lock inversion: ", 2, A(0), A(1)); // CHECK: Expecting lock inversion: [[A1:0x[a-f0-9]*]] [[A2:0x[a-f0-9]*]] Lock_0_1(); Lock_1_0(); @@ -174,7 +178,7 @@ class LockTest { fprintf(stderr, "Starting Test2\n"); // CHECK: Starting Test2 Init(5); - fprintf(stderr, "Expecting lock inversion: %p %p %p\n", A(0), A(1), A(2)); + print_address("Expecting lock inversion: ", 3, A(0), A(1), A(2)); // CHECK: Expecting lock inversion: [[A1:0x[a-f0-9]*]] [[A2:0x[a-f0-9]*]] [[A3:0x[a-f0-9]*]] Lock2(0, 1); Lock2(1, 2); diff --git a/src/compiler-rt/test/tsan/dl_iterate_phdr.cc b/src/compiler-rt/test/tsan/dl_iterate_phdr.cc index b230a920ac..b9ce615f82 100644 --- a/src/compiler-rt/test/tsan/dl_iterate_phdr.cc +++ b/src/compiler-rt/test/tsan/dl_iterate_phdr.cc @@ -1,7 +1,8 @@ // RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// If we mention TSAN_OPTIONS, the test won't run from test_output.sh script. +// dl_iterate_phdr doesn't exist on OS X. +// UNSUPPORTED: darwin #ifdef BUILD_SO diff --git a/src/compiler-rt/test/tsan/dlclose.cc b/src/compiler-rt/test/tsan/dlclose.cc index 1a93fe6617..d497fd704e 100644 --- a/src/compiler-rt/test/tsan/dlclose.cc +++ b/src/compiler-rt/test/tsan/dlclose.cc @@ -1,10 +1,8 @@ // RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// If we mention TSAN_OPTIONS, the test won't run from test_output.sh script. - // Test case for -// https://code.google.com/p/thread-sanitizer/issues/detail?id=80 +// https://github.com/google/sanitizers/issues/487 #ifdef BUILD_SO diff --git a/src/compiler-rt/test/tsan/fd_tid_recycled.cc b/src/compiler-rt/test/tsan/fd_tid_recycled.cc new file mode 100644 index 0000000000..d31478728b --- /dev/null +++ b/src/compiler-rt/test/tsan/fd_tid_recycled.cc @@ -0,0 +1,54 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +#include "test.h" + +int fds[2]; + +void *ThreadCreatePipe(void *x) { + pipe(fds); + return NULL; +} + +void *ThreadDummy(void *x) { + return NULL; +} + +void *ThreadWrite(void *x) { + write(fds[1], "a", 1); + barrier_wait(&barrier); + return NULL; +} + +void *ThreadClose(void *x) { + barrier_wait(&barrier); + close(fds[0]); + close(fds[1]); + return NULL; +} + +int main() { + barrier_init(&barrier, 2); + pthread_t t_create; + pthread_create(&t_create, NULL, ThreadCreatePipe, NULL); + pthread_join(t_create, NULL); + + for (int i = 0; i < 100; i++) { + pthread_t t_dummy; + pthread_create(&t_dummy, NULL, ThreadDummy, NULL); + pthread_join(t_dummy, NULL); + } + + pthread_t t[2]; + pthread_create(&t[0], NULL, ThreadWrite, NULL); + pthread_create(&t[1], NULL, ThreadClose, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); +} + +// CHECK-NOT: CHECK failed +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Write of size 8 +// CHECK: #0 close +// CHECK: #1 ThreadClose +// CHECK: Previous read of size 8 +// CHECK: #0 write +// CHECK: #1 ThreadWrite diff --git a/src/compiler-rt/test/tsan/fork_atexit.cc b/src/compiler-rt/test/tsan/fork_atexit.cc index 6801d3ffff..51a64fc264 100644 --- a/src/compiler-rt/test/tsan/fork_atexit.cc +++ b/src/compiler-rt/test/tsan/fork_atexit.cc @@ -1,4 +1,5 @@ -// RUN: %clangxx_tsan -O1 %s -o %t && TSAN_OPTIONS="atexit_sleep_ms=50" %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=atexit_sleep_ms=50 %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include #include #include diff --git a/src/compiler-rt/test/tsan/fork_deadlock.cc b/src/compiler-rt/test/tsan/fork_deadlock.cc index 9418800bd3..22bed086f7 100644 --- a/src/compiler-rt/test/tsan/fork_deadlock.cc +++ b/src/compiler-rt/test/tsan/fork_deadlock.cc @@ -1,4 +1,5 @@ -// RUN: %clangxx_tsan -O1 %s -o %t && TSAN_OPTIONS="atexit_sleep_ms=50" %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=atexit_sleep_ms=50 %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include "test.h" #include #include diff --git a/src/compiler-rt/test/tsan/fork_multithreaded.cc b/src/compiler-rt/test/tsan/fork_multithreaded.cc index 3ddb417c7c..b345f58ad0 100644 --- a/src/compiler-rt/test/tsan/fork_multithreaded.cc +++ b/src/compiler-rt/test/tsan/fork_multithreaded.cc @@ -1,5 +1,6 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -check-prefix=CHECK-DIE -// RUN: %clangxx_tsan -O1 %s -o %t && TSAN_OPTIONS="die_after_fork=0" %run %t 2>&1 | FileCheck %s -check-prefix=CHECK-NODIE +// RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=die_after_fork=0 %run %t 2>&1 | FileCheck %s -check-prefix=CHECK-NODIE +// UNSUPPORTED: darwin #include "test.h" #include #include diff --git a/src/compiler-rt/test/tsan/fork_multithreaded3.cc b/src/compiler-rt/test/tsan/fork_multithreaded3.cc index a651b3c18b..5b8c13eb8b 100644 --- a/src/compiler-rt/test/tsan/fork_multithreaded3.cc +++ b/src/compiler-rt/test/tsan/fork_multithreaded3.cc @@ -1,4 +1,5 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include #include #include diff --git a/src/compiler-rt/test/tsan/free_race.c b/src/compiler-rt/test/tsan/free_race.c index 63cee8c4ad..d508552c98 100644 --- a/src/compiler-rt/test/tsan/free_race.c +++ b/src/compiler-rt/test/tsan/free_race.c @@ -1,6 +1,6 @@ // RUN: %clang_tsan -O1 %s -o %t // RUN: %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOZUPP -// RUN: TSAN_OPTIONS="suppressions='%s.supp' print_suppressions=1" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-SUPP +// RUN: %env_tsan_opts=suppressions='%s.supp':print_suppressions=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-SUPP #include "test.h" diff --git a/src/compiler-rt/test/tsan/getline_nohang.cc b/src/compiler-rt/test/tsan/getline_nohang.cc index 89afbe1a66..d103839b8b 100644 --- a/src/compiler-rt/test/tsan/getline_nohang.cc +++ b/src/compiler-rt/test/tsan/getline_nohang.cc @@ -1,7 +1,7 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t // Make sure TSan doesn't deadlock on a file stream lock at program shutdown. -// See https://code.google.com/p/thread-sanitizer/issues/detail?id=47 +// See https://github.com/google/sanitizers/issues/454 #ifdef __FreeBSD__ #define _WITH_GETLINE // to declare getline() #endif diff --git a/src/compiler-rt/test/tsan/global_race.cc b/src/compiler-rt/test/tsan/global_race.cc index 3128ec4117..a35299619e 100644 --- a/src/compiler-rt/test/tsan/global_race.cc +++ b/src/compiler-rt/test/tsan/global_race.cc @@ -11,9 +11,7 @@ void *Thread(void *a) { int main() { barrier_init(&barrier, 2); - fprintf(stderr, "addr="); - print_address(GlobalData); - fprintf(stderr, "\n"); + print_address("addr=", 1, GlobalData); pthread_t t; pthread_create(&t, 0, Thread, 0); GlobalData[2] = 43; @@ -23,5 +21,5 @@ int main() { // CHECK: addr=[[ADDR:0x[0-9,a-f]+]] // CHECK: WARNING: ThreadSanitizer: data race -// CHECK: Location is global 'GlobalData' of size 40 at [[ADDR]] (global_race.cc.exe+0x{{[0-9,a-f]+}}) +// CHECK: Location is global 'GlobalData' {{(of size 40 )?}}at [[ADDR]] (global_race.cc.exe+0x{{[0-9,a-f]+}}) diff --git a/src/compiler-rt/test/tsan/global_race2.cc b/src/compiler-rt/test/tsan/global_race2.cc index 4ab2842e7e..95dff19978 100644 --- a/src/compiler-rt/test/tsan/global_race2.cc +++ b/src/compiler-rt/test/tsan/global_race2.cc @@ -11,9 +11,7 @@ void *Thread(void *a) { int main() { barrier_init(&barrier, 2); - fprintf(stderr, "addr2="); - print_address(&x); - fprintf(stderr, "\n"); + print_address("addr2=", 1, &x); pthread_t t; pthread_create(&t, 0, Thread, 0); x = 0; @@ -23,5 +21,5 @@ int main() { // CHECK: addr2=[[ADDR2:0x[0-9,a-f]+]] // CHECK: WARNING: ThreadSanitizer: data race -// CHECK: Location is global 'x' of size 4 at [[ADDR2]] ({{.*}}+0x{{[0-9,a-f]+}}) +// CHECK: Location is global 'x' {{(of size 4 )?}}at [[ADDR2]] ({{.*}}+0x{{[0-9,a-f]+}}) diff --git a/src/compiler-rt/test/tsan/global_race3.cc b/src/compiler-rt/test/tsan/global_race3.cc index 1531d7830f..e0d59d2844 100644 --- a/src/compiler-rt/test/tsan/global_race3.cc +++ b/src/compiler-rt/test/tsan/global_race3.cc @@ -16,9 +16,7 @@ void *Thread(void *a) { int main() { barrier_init(&barrier, 2); - fprintf(stderr, "addr3="); - print_address(XXX::YYY::ZZZ); - fprintf(stderr, "\n"); + print_address("addr3=", 1, XXX::YYY::ZZZ); pthread_t t; pthread_create(&t, 0, Thread, 0); XXX::YYY::ZZZ[0] = 0; @@ -28,4 +26,4 @@ int main() { // CHECK: addr3=[[ADDR3:0x[0-9,a-f]+]] // CHECK: WARNING: ThreadSanitizer: data race -// CHECK: Location is global 'XXX::YYY::ZZZ' of size 40 at [[ADDR3]] ({{.*}}+0x{{[0-9,a-f]+}}) +// CHECK: Location is global 'XXX::YYY::ZZZ' {{(of size 40 )?}}at [[ADDR3]] ({{.*}}+0x{{[0-9,a-f]+}}) diff --git a/src/compiler-rt/test/tsan/halt_on_error.cc b/src/compiler-rt/test/tsan/halt_on_error.cc index e55454b57c..5d481c3cbc 100644 --- a/src/compiler-rt/test/tsan/halt_on_error.cc +++ b/src/compiler-rt/test/tsan/halt_on_error.cc @@ -1,4 +1,4 @@ -// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="$TSAN_OPTIONS halt_on_error=1" %deflake %run %t | FileCheck %s +// RUN: %clang_tsan -O1 %s -o %t && %env_tsan_opts=halt_on_error=1 %deflake %run %t | FileCheck %s #include "test.h" int X; diff --git a/src/compiler-rt/test/tsan/ignore_lib0.cc b/src/compiler-rt/test/tsan/ignore_lib0.cc index 122ec1f456..d6ae72f316 100644 --- a/src/compiler-rt/test/tsan/ignore_lib0.cc +++ b/src/compiler-rt/test/tsan/ignore_lib0.cc @@ -1,9 +1,9 @@ // RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib0.so // RUN: %clangxx_tsan -O1 %s -L%T -lignore_lib0 -o %t // RUN: echo running w/o suppressions: -// RUN: LD_LIBRARY_PATH=%T${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOSUPP +// RUN: env LD_LIBRARY_PATH=%T${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOSUPP // RUN: echo running with suppressions: -// RUN: LD_LIBRARY_PATH=%T${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP +// RUN: env LD_LIBRARY_PATH=%T${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP // Tests that interceptors coming from a library specified in called_from_lib // suppression are ignored. diff --git a/src/compiler-rt/test/tsan/ignore_lib1.cc b/src/compiler-rt/test/tsan/ignore_lib1.cc index 1283cfdb4e..e6a13a3943 100644 --- a/src/compiler-rt/test/tsan/ignore_lib1.cc +++ b/src/compiler-rt/test/tsan/ignore_lib1.cc @@ -3,7 +3,7 @@ // RUN: echo running w/o suppressions: // RUN: %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOSUPP // RUN: echo running with suppressions: -// RUN: TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP +// RUN: %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP // Tests that interceptors coming from a dynamically loaded library specified // in called_from_lib suppression are ignored. diff --git a/src/compiler-rt/test/tsan/ignore_lib2.cc b/src/compiler-rt/test/tsan/ignore_lib2.cc index ad3107cf53..4f584b1466 100644 --- a/src/compiler-rt/test/tsan/ignore_lib2.cc +++ b/src/compiler-rt/test/tsan/ignore_lib2.cc @@ -1,7 +1,7 @@ // RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib2_0.so // RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib2_1.so // RUN: %clangxx_tsan -O1 %s -o %t -// RUN: TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %deflake %run %t | FileCheck %s +// RUN: %env_tsan_opts=suppressions='%s.supp' %deflake %run %t | FileCheck %s // Tests that called_from_lib suppression matched against 2 libraries // causes program crash (this is not supported). diff --git a/src/compiler-rt/test/tsan/ignore_lib3.cc b/src/compiler-rt/test/tsan/ignore_lib3.cc index 79e4ba1812..3f7be5cf82 100644 --- a/src/compiler-rt/test/tsan/ignore_lib3.cc +++ b/src/compiler-rt/test/tsan/ignore_lib3.cc @@ -1,6 +1,6 @@ // RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib3.so // RUN: %clangxx_tsan -O1 %s -o %t -// RUN: TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %deflake %run %t | FileCheck %s +// RUN: %env_tsan_opts=suppressions='%s.supp' %deflake %run %t | FileCheck %s // Tests that unloading of a library matched against called_from_lib suppression // causes program crash (this is not supported). diff --git a/src/compiler-rt/test/tsan/inlined_memcpy_race.cc b/src/compiler-rt/test/tsan/inlined_memcpy_race.cc index e3ed07abcf..720f2bfcac 100644 --- a/src/compiler-rt/test/tsan/inlined_memcpy_race.cc +++ b/src/compiler-rt/test/tsan/inlined_memcpy_race.cc @@ -32,6 +32,6 @@ int main() { // CHECK: #0 memset // CHECK: #1 MemSetThread // CHECK: Previous write -// CHECK: #0 memcpy +// CHECK: #0 {{(memcpy|memmove)}} // CHECK: #1 MemCpyThread diff --git a/src/compiler-rt/test/tsan/java_race_pc.cc b/src/compiler-rt/test/tsan/java_race_pc.cc index 015a0b1f43..0745ade6c4 100644 --- a/src/compiler-rt/test/tsan/java_race_pc.cc +++ b/src/compiler-rt/test/tsan/java_race_pc.cc @@ -1,4 +1,8 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// This test fails on powerpc64 on both VMA (44 and 46). +// The Tsan report is returning wrong information about +// the location of the race. +// XFAIL: powerpc64 #include "java.h" void foobar() { diff --git a/src/compiler-rt/test/tsan/lit.cfg b/src/compiler-rt/test/tsan/lit.cfg index b0c6671832..d141fc2285 100644 --- a/src/compiler-rt/test/tsan/lit.cfg +++ b/src/compiler-rt/test/tsan/lit.cfg @@ -12,20 +12,25 @@ def get_required_attr(config, attr_name): return attr_value # Setup config name. -config.name = 'ThreadSanitizer' +config.name = 'ThreadSanitizer' + config.name_suffix # Setup source root. config.test_source_root = os.path.dirname(__file__) # Setup environment variables for running ThreadSanitizer. -tsan_options = "atexit_sleep_ms=0" +default_tsan_opts = "atexit_sleep_ms=0" if config.host_os == 'Darwin': # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. - tsan_options += ':abort_on_error=0' + default_tsan_opts += ':abort_on_error=0' -config.environment['TSAN_OPTIONS'] = tsan_options +# Platform-specific default TSAN_OPTIONS for lit tests. +if default_tsan_opts: + config.environment['TSAN_OPTIONS'] = default_tsan_opts + default_tsan_opts += ':' +config.substitutions.append(('%env_tsan_opts=', + 'env TSAN_OPTIONS=' + default_tsan_opts)) # GCC driver doesn't add necessary compile/link flags with -fsanitize=thread. if config.compiler_id == 'GNU': @@ -34,16 +39,18 @@ else: extra_cflags = [] # Setup default compiler flags used with -fsanitize=thread option. -clang_tsan_cflags = ["-fsanitize=thread", - "-Wall", - "-m64"] + config.debug_info_flags + extra_cflags +clang_tsan_cflags = (["-fsanitize=thread", + "-Wall"] + + [config.target_cflags] + + config.debug_info_flags + + extra_cflags) clang_tsan_cxxflags = config.cxx_mode_flags + clang_tsan_cflags # Add additional flags if we're using instrumented libc++. # Instrumented libcxx currently not supported on Darwin. if config.has_libcxx and config.host_os != 'Darwin': # FIXME: Dehardcode this path somehow. libcxx_path = os.path.join(config.compiler_rt_obj_root, "lib", - "tsan", "libcxx_tsan") + "tsan", "libcxx_tsan_" + config.arch) libcxx_incdir = os.path.join(libcxx_path, "include", "c++", "v1") libcxx_libdir = os.path.join(libcxx_path, "lib") libcxx_so = os.path.join(libcxx_libdir, "libc++.so") @@ -64,7 +71,7 @@ config.substitutions.append( ('CHECK-%os', ("CHECK-" + config.host_os))) config.substitutions.append( ("%deflake ", os.path.join(os.path.dirname(__file__), "deflake.bash")) ) # Default test suffixes. -config.suffixes = ['.c', '.cc', '.cpp'] +config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm'] # ThreadSanitizer tests are currently supported on FreeBSD, Linux and Darwin. if config.host_os not in ['FreeBSD', 'Linux', 'Darwin']: diff --git a/src/compiler-rt/test/tsan/lit.site.cfg.in b/src/compiler-rt/test/tsan/lit.site.cfg.in index 5190b21117..08d4c1e00c 100644 --- a/src/compiler-rt/test/tsan/lit.site.cfg.in +++ b/src/compiler-rt/test/tsan/lit.site.cfg.in @@ -1,7 +1,10 @@ ## Autogenerated by LLVM/Clang configuration. # Do not edit! +config.name_suffix = "@TSAN_TEST_CONFIG_SUFFIX@" +config.arch = "@arch@" config.has_libcxx = @TSAN_HAS_LIBCXX@ +config.target_cflags = "@TSAN_TEST_TARGET_CFLAGS@" # Load common config for all compiler-rt lit tests. lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") diff --git a/src/compiler-rt/test/tsan/load_shared_lib.cc b/src/compiler-rt/test/tsan/load_shared_lib.cc index b7934b82df..f02280895f 100644 --- a/src/compiler-rt/test/tsan/load_shared_lib.cc +++ b/src/compiler-rt/test/tsan/load_shared_lib.cc @@ -3,7 +3,7 @@ // symbolized correctly. // RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so -// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// RUN: %clangxx_tsan -O1 %s -o %t -rdynamic && %deflake %run %t | FileCheck %s #ifdef BUILD_SO diff --git a/src/compiler-rt/test/tsan/longjmp.cc b/src/compiler-rt/test/tsan/longjmp.cc index 9ac6b99c2b..d642067391 100644 --- a/src/compiler-rt/test/tsan/longjmp.cc +++ b/src/compiler-rt/test/tsan/longjmp.cc @@ -1,8 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// Longjmp assembly has not been implemented for mips64 or aarch64 yet +// Longjmp assembly has not been implemented for mips64 yet // XFAIL: mips64 -// XFAIL: aarch64 #include #include diff --git a/src/compiler-rt/test/tsan/longjmp2.cc b/src/compiler-rt/test/tsan/longjmp2.cc index dfbd84b495..eee423dc5f 100644 --- a/src/compiler-rt/test/tsan/longjmp2.cc +++ b/src/compiler-rt/test/tsan/longjmp2.cc @@ -1,8 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// Longjmp assembly has not been implemented for mips64 or aarch64 yet +// Longjmp assembly has not been implemented for mips64 yet // XFAIL: mips64 -// XFAIL: aarch64 #include #include diff --git a/src/compiler-rt/test/tsan/longjmp3.cc b/src/compiler-rt/test/tsan/longjmp3.cc index df426fac28..79965c4193 100644 --- a/src/compiler-rt/test/tsan/longjmp3.cc +++ b/src/compiler-rt/test/tsan/longjmp3.cc @@ -1,8 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s -// Longjmp assembly has not been implemented for mips64 or aarch64 yet +// Longjmp assembly has not been implemented for mips64 yet // XFAIL: mips64 -// XFAIL: aarch64 #include #include diff --git a/src/compiler-rt/test/tsan/longjmp4.cc b/src/compiler-rt/test/tsan/longjmp4.cc index 9f5d6d1a83..c858399733 100644 --- a/src/compiler-rt/test/tsan/longjmp4.cc +++ b/src/compiler-rt/test/tsan/longjmp4.cc @@ -1,8 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s -// Longjmp assembly has not been implemented for mips64 or aarch64 yet +// Longjmp assembly has not been implemented for mips64 yet // XFAIL: mips64 -// XFAIL: aarch64 #include #include diff --git a/src/compiler-rt/test/tsan/malloc_overflow.cc b/src/compiler-rt/test/tsan/malloc_overflow.cc index dadc94484f..b2f9b0f577 100644 --- a/src/compiler-rt/test/tsan/malloc_overflow.cc +++ b/src/compiler-rt/test/tsan/malloc_overflow.cc @@ -1,5 +1,5 @@ // RUN: %clangxx_tsan -O1 %s -o %t -// RUN: TSAN_OPTIONS=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s #include #include diff --git a/src/compiler-rt/test/tsan/map32bit.cc b/src/compiler-rt/test/tsan/map32bit.cc index f23d7f76e6..0411f29a95 100644 --- a/src/compiler-rt/test/tsan/map32bit.cc +++ b/src/compiler-rt/test/tsan/map32bit.cc @@ -5,11 +5,15 @@ #include // Test for issue: -// https://code.google.com/p/thread-sanitizer/issues/detail?id=5 +// https://github.com/google/sanitizers/issues/412 // MAP_32BIT flag for mmap is supported only for x86_64. // XFAIL: mips64 // XFAIL: aarch64 +// XFAIL: powerpc64 + +// MAP_32BIT doesn't exist on OS X. +// UNSUPPORTED: darwin void *Thread(void *ptr) { *(int*)ptr = 42; diff --git a/src/compiler-rt/test/tsan/memcmp_race.cc b/src/compiler-rt/test/tsan/memcmp_race.cc index 465d1d0208..b76f427e12 100644 --- a/src/compiler-rt/test/tsan/memcmp_race.cc +++ b/src/compiler-rt/test/tsan/memcmp_race.cc @@ -23,7 +23,7 @@ void *Thread2(void *x) { int main() { barrier_init(&barrier, 2); - fprintf(stderr, "addr=%p\n", &data0[5]); + print_address("addr=", 1, &data0[5]); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); pthread_create(&t[1], NULL, Thread2, NULL); @@ -35,7 +35,7 @@ int main() { // CHECK: addr=[[ADDR:0x[0-9,a-f]+]] // CHECK: WARNING: ThreadSanitizer: data race // CHECK: Write of size 1 at [[ADDR]] by thread T2: -// CHECK: #0 memcpy +// CHECK: #0 {{(memcpy|memmove)}} // CHECK: #1 Thread2 // CHECK: Previous read of size 1 at [[ADDR]] by thread T1: // CHECK: #0 memcmp diff --git a/src/compiler-rt/test/tsan/memcpy_race.cc b/src/compiler-rt/test/tsan/memcpy_race.cc index d49577306d..4a098c0405 100644 --- a/src/compiler-rt/test/tsan/memcpy_race.cc +++ b/src/compiler-rt/test/tsan/memcpy_race.cc @@ -22,7 +22,7 @@ void *Thread2(void *x) { int main() { barrier_init(&barrier, 2); - fprintf(stderr, "addr=%p\n", &data[5]); + print_address("addr=", 1, &data[5]); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); pthread_create(&t[1], NULL, Thread2, NULL); @@ -34,8 +34,8 @@ int main() { // CHECK: addr=[[ADDR:0x[0-9,a-f]+]] // CHECK: WARNING: ThreadSanitizer: data race // CHECK: Write of size 1 at [[ADDR]] by thread T2: -// CHECK: #0 memcpy +// CHECK: #0 {{(memcpy|memmove)}} // CHECK: #1 Thread2 // CHECK: Previous write of size 1 at [[ADDR]] by thread T1: -// CHECK: #0 memcpy +// CHECK: #0 {{(memcpy|memmove)}} // CHECK: #1 Thread1 diff --git a/src/compiler-rt/test/tsan/mmap_large.cc b/src/compiler-rt/test/tsan/mmap_large.cc index d31ea3603d..764e954f2b 100644 --- a/src/compiler-rt/test/tsan/mmap_large.cc +++ b/src/compiler-rt/test/tsan/mmap_large.cc @@ -16,13 +16,15 @@ int main() { const size_t kLog2Size = 39; #elif defined(__mips64) || defined(__aarch64__) const size_t kLog2Size = 32; +#elif defined(__powerpc64__) + const size_t kLog2Size = 39; #endif const uintptr_t kLocation = 0x40ULL << kLog2Size; void *p = mmap( reinterpret_cast(kLocation), 1ULL << kLog2Size, PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, + MAP_PRIVATE|MAP_ANON|MAP_NORESERVE, -1, 0); fprintf(stderr, "DONE %p %d\n", p, errno); return p == MAP_FAILED; diff --git a/src/compiler-rt/test/tsan/mmap_stress.cc b/src/compiler-rt/test/tsan/mmap_stress.cc index 5e3904adf9..e01e7e92b8 100644 --- a/src/compiler-rt/test/tsan/mmap_stress.cc +++ b/src/compiler-rt/test/tsan/mmap_stress.cc @@ -9,8 +9,11 @@ void *SubWorker(void *arg) { for (int i = 0; i < 500; i++) { int *ptr = (int*)mmap(0, kMmapSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + if (ptr == MAP_FAILED) + exit(printf("mmap failed: %d\n", errno)); *ptr = 42; - munmap(ptr, kMmapSize); + if (munmap(ptr, kMmapSize)) + exit(printf("munmap failed: %d\n", errno)); } return 0; } @@ -18,29 +21,41 @@ void *SubWorker(void *arg) { 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); + for (int i = 0; i < 4; i++) { + if (pthread_create(&th[i], 0, SubWorker, 0)) + exit(printf("pthread_create failed: %d\n", errno)); + } + for (int i = 0; i < 4; i++) { + if (pthread_join(th[i], 0)) + exit(printf("pthread_join failed: %d\n", errno)); + } 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); + for (int i = 0; i < 4; i++) { + if (pthread_create(&th[i], 0, Worker1, 0)) + exit(printf("pthread_create failed: %d\n", errno)); + } + for (int i = 0; i < 4; i++) { + if (pthread_join(th[i], 0)) + exit(printf("pthread_join failed: %d\n", errno)); + } 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); + for (int i = 0; i < 4; i++) { + if (pthread_create(&th[i], 0, Worker, 0)) + exit(printf("pthread_create failed: %d\n", errno)); + } + for (int i = 0; i < 4; i++) { + if (pthread_join(th[i], 0)) + exit(printf("pthread_join failed: %d\n", errno)); + } fprintf(stderr, "DONE\n"); } diff --git a/src/compiler-rt/test/tsan/mop_with_offset.cc b/src/compiler-rt/test/tsan/mop_with_offset.cc index c67e81e09c..e2496d099e 100644 --- a/src/compiler-rt/test/tsan/mop_with_offset.cc +++ b/src/compiler-rt/test/tsan/mop_with_offset.cc @@ -18,8 +18,8 @@ void *Thread2(void *x) { int main() { barrier_init(&barrier, 2); int *data = new int(42); - fprintf(stderr, "ptr1=%p\n", data); - fprintf(stderr, "ptr2=%p\n", (char*)data + 2); + print_address("ptr1=", 1, data); + print_address("ptr2=", 1, (char*)data + 2); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, data); pthread_create(&t[1], NULL, Thread2, data); diff --git a/src/compiler-rt/test/tsan/mop_with_offset2.cc b/src/compiler-rt/test/tsan/mop_with_offset2.cc index 460267359c..73c53f5123 100644 --- a/src/compiler-rt/test/tsan/mop_with_offset2.cc +++ b/src/compiler-rt/test/tsan/mop_with_offset2.cc @@ -18,8 +18,8 @@ void *Thread2(void *x) { int main() { barrier_init(&barrier, 2); int *data = new int(42); - fprintf(stderr, "ptr1=%p\n", data); - fprintf(stderr, "ptr2=%p\n", (char*)data + 2); + print_address("ptr1=", 1, data); + print_address("ptr2=", 1, (char*)data + 2); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, data); pthread_create(&t[1], NULL, Thread2, data); diff --git a/src/compiler-rt/test/tsan/mutex_cycle2.c b/src/compiler-rt/test/tsan/mutex_cycle2.c index 85d19a0d0c..32659d4eec 100644 --- a/src/compiler-rt/test/tsan/mutex_cycle2.c +++ b/src/compiler-rt/test/tsan/mutex_cycle2.c @@ -1,11 +1,11 @@ // RUN: %clangxx_tsan %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s -// RUN: TSAN_OPTIONS=detect_deadlocks=1 not %run %t 2>&1 | FileCheck %s -// RUN: TSAN_OPTIONS=detect_deadlocks=0 %run %t 2>&1 | FileCheck %s --check-prefix=DISABLED +// RUN: %env_tsan_opts=detect_deadlocks=1 not %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=detect_deadlocks=0 %run %t 2>&1 | FileCheck %s --check-prefix=DISABLED // RUN: echo "deadlock:main" > %t.supp -// RUN: TSAN_OPTIONS="suppressions='%t.supp'" %run %t 2>&1 | FileCheck %s --check-prefix=DISABLED +// RUN: %env_tsan_opts=suppressions='%t.supp' %run %t 2>&1 | FileCheck %s --check-prefix=DISABLED // RUN: echo "deadlock:zzzz" > %t.supp -// RUN: TSAN_OPTIONS="suppressions='%t.supp'" not %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=suppressions='%t.supp' not %run %t 2>&1 | FileCheck %s #include #include diff --git a/src/compiler-rt/test/tsan/mutexset1.cc b/src/compiler-rt/test/tsan/mutexset1.cc index 407cfe5bd9..8403b34017 100644 --- a/src/compiler-rt/test/tsan/mutexset1.cc +++ b/src/compiler-rt/test/tsan/mutexset1.cc @@ -26,7 +26,7 @@ int main() { // CHECK: Previous write of size 4 at {{.*}} by thread T2: // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset1.cc:[[@LINE+1]] + // CHECK: #1 main {{.*}}mutexset1.cc:[[@LINE+1]] pthread_mutex_init(&mtx, 0); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); diff --git a/src/compiler-rt/test/tsan/mutexset2.cc b/src/compiler-rt/test/tsan/mutexset2.cc index 2a3e5bb95e..5f7c0c41bb 100644 --- a/src/compiler-rt/test/tsan/mutexset2.cc +++ b/src/compiler-rt/test/tsan/mutexset2.cc @@ -26,7 +26,7 @@ int main() { // CHECK: (mutexes: write [[M1:M[0-9]+]]): // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset2.cc:[[@LINE+1]] + // CHECK: #1 main {{.*}}mutexset2.cc:[[@LINE+1]] pthread_mutex_init(&mtx, 0); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); diff --git a/src/compiler-rt/test/tsan/mutexset3.cc b/src/compiler-rt/test/tsan/mutexset3.cc index ce64cf86e3..24a9d9bf01 100644 --- a/src/compiler-rt/test/tsan/mutexset3.cc +++ b/src/compiler-rt/test/tsan/mutexset3.cc @@ -29,10 +29,10 @@ int main() { // CHECK: Previous write of size 4 at {{.*}} by thread T2: // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset3.cc:[[@LINE+4]] + // CHECK: #1 main {{.*}}mutexset3.cc:[[@LINE+4]] // CHECK: Mutex [[M2]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset3.cc:[[@LINE+2]] + // CHECK: #1 main {{.*}}mutexset3.cc:[[@LINE+2]] pthread_mutex_init(&mtx1, 0); pthread_mutex_init(&mtx2, 0); pthread_t t[2]; diff --git a/src/compiler-rt/test/tsan/mutexset4.cc b/src/compiler-rt/test/tsan/mutexset4.cc index b961efd213..5d8ea9e400 100644 --- a/src/compiler-rt/test/tsan/mutexset4.cc +++ b/src/compiler-rt/test/tsan/mutexset4.cc @@ -29,10 +29,10 @@ int main() { // CHECK: (mutexes: write [[M1:M[0-9]+]], write [[M2:M[0-9]+]]): // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset4.cc:[[@LINE+4]] + // CHECK: #1 main {{.*}}mutexset4.cc:[[@LINE+4]] // CHECK: Mutex [[M2]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset4.cc:[[@LINE+2]] + // CHECK: #1 main {{.*}}mutexset4.cc:[[@LINE+2]] pthread_mutex_init(&mtx1, 0); pthread_mutex_init(&mtx2, 0); pthread_t t[2]; diff --git a/src/compiler-rt/test/tsan/mutexset5.cc b/src/compiler-rt/test/tsan/mutexset5.cc index 8ef9af0ced..b5f4e77949 100644 --- a/src/compiler-rt/test/tsan/mutexset5.cc +++ b/src/compiler-rt/test/tsan/mutexset5.cc @@ -30,10 +30,10 @@ int main() { // CHECK: (mutexes: write [[M2:M[0-9]+]]): // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset5.cc:[[@LINE+4]] + // CHECK: #1 main {{.*}}mutexset5.cc:[[@LINE+4]] // CHECK: Mutex [[M2]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset5.cc:[[@LINE+5]] + // CHECK: #1 main {{.*}}mutexset5.cc:[[@LINE+5]] pthread_mutex_init(&mtx1, 0); pthread_mutex_init(&mtx2, 0); pthread_t t[2]; diff --git a/src/compiler-rt/test/tsan/mutexset6.cc b/src/compiler-rt/test/tsan/mutexset6.cc index f4251db697..ca349aaeee 100644 --- a/src/compiler-rt/test/tsan/mutexset6.cc +++ b/src/compiler-rt/test/tsan/mutexset6.cc @@ -3,7 +3,7 @@ int Global; pthread_mutex_t mtx1; -pthread_spinlock_t mtx2; +pthread_mutex_t mtx2; pthread_rwlock_t mtx3; void *Thread1(void *x) { @@ -17,10 +17,10 @@ void *Thread1(void *x) { void *Thread2(void *x) { pthread_mutex_lock(&mtx1); pthread_mutex_unlock(&mtx1); - pthread_spin_lock(&mtx2); + pthread_mutex_lock(&mtx2); pthread_rwlock_rdlock(&mtx3); Global--; - pthread_spin_unlock(&mtx2); + pthread_mutex_unlock(&mtx2); pthread_rwlock_unlock(&mtx3); barrier_wait(&barrier); return NULL; @@ -34,13 +34,13 @@ int main() { // CHECK: Previous write of size 4 at {{.*}} by thread T2 // CHECK: (mutexes: write [[M2:M[0-9]+]], read [[M3:M[0-9]+]]): // CHECK: Mutex [[M1]] (0x{{.*}}) created at: - // CHECK: #1 main {{.*}}/mutexset6.cc:[[@LINE+5]] + // CHECK: #1 main {{.*}}mutexset6.cc:[[@LINE+5]] // CHECK: Mutex [[M2]] (0x{{.*}}) created at: - // CHECK: #1 main {{.*}}/mutexset6.cc:[[@LINE+4]] + // CHECK: #1 main {{.*}}mutexset6.cc:[[@LINE+4]] // CHECK: Mutex [[M3]] (0x{{.*}}) created at: - // CHECK: #1 main {{.*}}/mutexset6.cc:[[@LINE+3]] + // CHECK: #1 main {{.*}}mutexset6.cc:[[@LINE+3]] pthread_mutex_init(&mtx1, 0); - pthread_spin_init(&mtx2, 0); + pthread_mutex_init(&mtx2, 0); pthread_rwlock_init(&mtx3, 0); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); @@ -48,6 +48,6 @@ int main() { pthread_join(t[0], NULL); pthread_join(t[1], NULL); pthread_mutex_destroy(&mtx1); - pthread_spin_destroy(&mtx2); + pthread_mutex_destroy(&mtx2); pthread_rwlock_destroy(&mtx3); } diff --git a/src/compiler-rt/test/tsan/mutexset8.cc b/src/compiler-rt/test/tsan/mutexset8.cc index 40d5d043de..69854e2ffa 100644 --- a/src/compiler-rt/test/tsan/mutexset8.cc +++ b/src/compiler-rt/test/tsan/mutexset8.cc @@ -26,7 +26,7 @@ int main() { // CHECK: Previous write of size 4 at {{.*}} by thread T2: // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init - // CHECK: #1 main {{.*}}/mutexset8.cc + // CHECK: #1 main {{.*}}mutexset8.cc mtx = new pthread_mutex_t; pthread_mutex_init(mtx, 0); pthread_t t[2]; diff --git a/src/compiler-rt/test/tsan/pie_test.cc b/src/compiler-rt/test/tsan/pie_test.cc new file mode 100644 index 0000000000..8635f9cd40 --- /dev/null +++ b/src/compiler-rt/test/tsan/pie_test.cc @@ -0,0 +1,12 @@ +// Check if tsan work with PIE binaries. +// RUN: %clang_tsan %s -pie -fpic -o %t && %run %t + +// Some kernels might map PIE segments outside the current segment +// mapping defined for x86 [1]. +// [1] https://git.kernel.org/linus/d1fd836dcf00d2028c700c7e44d2c23404062c90 + +// UNSUPPORTED: x86 + +int main(void) { + return 0; +} diff --git a/src/compiler-rt/test/tsan/printf-1.c b/src/compiler-rt/test/tsan/printf-1.c index 9116c956e3..c8414f834b 100644 --- a/src/compiler-rt/test/tsan/printf-1.c +++ b/src/compiler-rt/test/tsan/printf-1.c @@ -1,6 +1,6 @@ // RUN: %clang_tsan -O2 %s -o %t -// RUN: ASAN_OPTIONS=check_printf=1 %run %t 2>&1 | FileCheck %s -// RUN: ASAN_OPTIONS=check_printf=0 %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=check_printf=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=check_printf=0 %run %t 2>&1 | FileCheck %s // RUN: %run %t 2>&1 | FileCheck %s #include diff --git a/src/compiler-rt/test/tsan/pthread_atfork_deadlock.c b/src/compiler-rt/test/tsan/pthread_atfork_deadlock.c index 4aeec82b68..01107ee669 100644 --- a/src/compiler-rt/test/tsan/pthread_atfork_deadlock.c +++ b/src/compiler-rt/test/tsan/pthread_atfork_deadlock.c @@ -1,6 +1,6 @@ // RUN: %clang_tsan -O1 %s -lpthread -o %t && %deflake %run %t | FileCheck %s // Regression test for -// https://code.google.com/p/thread-sanitizer/issues/detail?id=61 +// https://github.com/google/sanitizers/issues/468 // When the data race was reported, pthread_atfork() handler used to be // executed which caused another race report in the same thread, which resulted // in a deadlock. diff --git a/src/compiler-rt/test/tsan/race_on_barrier.c b/src/compiler-rt/test/tsan/race_on_barrier.c index cf8a4cb992..66fd339eb9 100644 --- a/src/compiler-rt/test/tsan/race_on_barrier.c +++ b/src/compiler-rt/test/tsan/race_on_barrier.c @@ -1,4 +1,8 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s + +// pthread barriers are not available on OS X +// UNSUPPORTED: darwin + #include "test.h" pthread_barrier_t B; diff --git a/src/compiler-rt/test/tsan/race_on_barrier2.c b/src/compiler-rt/test/tsan/race_on_barrier2.c index 98c028e19f..49adb62312 100644 --- a/src/compiler-rt/test/tsan/race_on_barrier2.c +++ b/src/compiler-rt/test/tsan/race_on_barrier2.c @@ -1,4 +1,8 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s + +// pthread barriers are not available on OS X +// UNSUPPORTED: darwin + #include #include #include diff --git a/src/compiler-rt/test/tsan/race_on_heap.cc b/src/compiler-rt/test/tsan/race_on_heap.cc index a66e0c4f93..6c2defc835 100644 --- a/src/compiler-rt/test/tsan/race_on_heap.cc +++ b/src/compiler-rt/test/tsan/race_on_heap.cc @@ -2,6 +2,7 @@ #include #include #include +#include "test.h" void *Thread1(void *p) { *(int*)p = 42; @@ -26,7 +27,7 @@ int main() { pthread_t t[2]; pthread_create(&t[0], 0, AllocThread, 0); pthread_join(t[0], &p); - fprintf(stderr, "addr=%p\n", p); + print_address("addr=", 1, p); pthread_create(&t[0], 0, Thread1, (char*)p + 16); pthread_create(&t[1], 0, Thread2, (char*)p + 16); pthread_join(t[0], 0); diff --git a/src/compiler-rt/test/tsan/race_on_mutex.c b/src/compiler-rt/test/tsan/race_on_mutex.c index 7bd461bf37..d998fdca2d 100644 --- a/src/compiler-rt/test/tsan/race_on_mutex.c +++ b/src/compiler-rt/test/tsan/race_on_mutex.c @@ -1,4 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// This test fails on powerpc64 (VMA=46). +// The size of the write reported by Tsan for T1 is 8 instead of 1. +// XFAIL: powerpc64-unknown-linux-gnu #include "test.h" pthread_mutex_t Mtx; @@ -35,7 +38,7 @@ int main() { // CHECK: WARNING: ThreadSanitizer: data race // CHECK-NEXT: Atomic read of size 1 at {{.*}} by thread T2: // CHECK-NEXT: #0 pthread_mutex_lock -// CHECK-NEXT: #1 Thread2{{.*}} {{.*}}race_on_mutex.c:18{{(:3)?}} ({{.*}}) +// CHECK-NEXT: #1 Thread2{{.*}} {{.*}}race_on_mutex.c:21{{(:3)?}} ({{.*}}) // CHECK: Previous write of size 1 at {{.*}} by thread T1: // CHECK-NEXT: #0 pthread_mutex_init {{.*}} ({{.*}}) -// CHECK-NEXT: #1 Thread1{{.*}} {{.*}}race_on_mutex.c:8{{(:3)?}} ({{.*}}) +// CHECK-NEXT: #1 Thread1{{.*}} {{.*}}race_on_mutex.c:11{{(:3)?}} ({{.*}}) diff --git a/src/compiler-rt/test/tsan/race_on_speculative_load.cc b/src/compiler-rt/test/tsan/race_on_speculative_load.cc index b50b69677d..dd40daeb5c 100644 --- a/src/compiler-rt/test/tsan/race_on_speculative_load.cc +++ b/src/compiler-rt/test/tsan/race_on_speculative_load.cc @@ -1,5 +1,5 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t | FileCheck %s -// Regtest for https://code.google.com/p/thread-sanitizer/issues/detail?id=40 +// Regtest for https://github.com/google/sanitizers/issues/447 // This is a correct program and tsan should not report a race. #include "test.h" diff --git a/src/compiler-rt/test/tsan/race_top_suppression.cc b/src/compiler-rt/test/tsan/race_top_suppression.cc index 7d42dbf3b4..bd5c1bd5f4 100644 --- a/src/compiler-rt/test/tsan/race_top_suppression.cc +++ b/src/compiler-rt/test/tsan/race_top_suppression.cc @@ -1,6 +1,6 @@ // RUN: echo "race_top:TopFunction" > %t.supp // RUN: %clangxx_tsan -O1 %s -o %t -// RUN: TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%t.supp'" %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=suppressions='%t.supp' %run %t 2>&1 | FileCheck %s // RUN: rm %t.supp #include "test.h" diff --git a/src/compiler-rt/test/tsan/race_top_suppression1.cc b/src/compiler-rt/test/tsan/race_top_suppression1.cc index 881e661ba7..e34385a9b5 100644 --- a/src/compiler-rt/test/tsan/race_top_suppression1.cc +++ b/src/compiler-rt/test/tsan/race_top_suppression1.cc @@ -1,6 +1,6 @@ // RUN: echo "race_top:TopFunction" > %t.supp // RUN: %clangxx_tsan -O1 %s -o %t -// RUN: TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%t.supp'" %deflake %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=suppressions='%t.supp' %deflake %run %t 2>&1 | FileCheck %s // RUN: rm %t.supp #include "test.h" diff --git a/src/compiler-rt/test/tsan/real_deadlock_detector_stress_test.cc b/src/compiler-rt/test/tsan/real_deadlock_detector_stress_test.cc index 5576f12589..feb1117e80 100644 --- a/src/compiler-rt/test/tsan/real_deadlock_detector_stress_test.cc +++ b/src/compiler-rt/test/tsan/real_deadlock_detector_stress_test.cc @@ -8,6 +8,7 @@ #include #include #include +#include const int kThreads = 4; const int kMutexes = 16 << 10; @@ -165,9 +166,9 @@ void *Thread(void *seed) { } int main() { - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - unsigned s = (unsigned)ts.tv_nsec; + struct timeval tv; + gettimeofday(&tv, NULL); + unsigned s = tv.tv_sec + tv.tv_usec; fprintf(stderr, "seed %d\n", s); srand(s); for (int i = 0; i < kMutexes; i++) diff --git a/src/compiler-rt/test/tsan/setuid2.c b/src/compiler-rt/test/tsan/setuid2.c index 67a6fd14db..9dbb6577e1 100644 --- a/src/compiler-rt/test/tsan/setuid2.c +++ b/src/compiler-rt/test/tsan/setuid2.c @@ -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: %clang_tsan -O1 %s -o %t && %env_tsan_opts=flush_memory_ms=1:memory_limit_mb=1 %run %t 2>&1 | FileCheck %s #include "test.h" #include #include @@ -7,11 +7,11 @@ // Test that setuid call works in presence of stoptheworld. int main() { - struct timespec tp0, tp1; - clock_gettime(CLOCK_MONOTONIC, &tp0); - clock_gettime(CLOCK_MONOTONIC, &tp1); - while (tp1.tv_sec - tp0.tv_sec < 3) { - clock_gettime(CLOCK_MONOTONIC, &tp1); + unsigned long long tp0, tp1; + tp0 = monotonic_clock_ns(); + tp1 = monotonic_clock_ns(); + while (tp1 - tp0 < 3 * 1000000000ull) { + tp1 = monotonic_clock_ns(); setuid(0); } fprintf(stderr, "DONE\n"); diff --git a/src/compiler-rt/test/tsan/signal_cond.cc b/src/compiler-rt/test/tsan/signal_cond.cc index f5eae745d4..beb2e0266e 100644 --- a/src/compiler-rt/test/tsan/signal_cond.cc +++ b/src/compiler-rt/test/tsan/signal_cond.cc @@ -6,17 +6,16 @@ #include // Test that signals can be delivered to blocked pthread_cond_wait. -// https://code.google.com/p/thread-sanitizer/issues/detail?id=91 +// https://github.com/google/sanitizers/issues/498 int g_thread_run = 1; pthread_mutex_t mutex; pthread_cond_t cond; -sem_t sem; void sig_handler(int sig) { (void)sig; write(1, "SIGNAL\n", sizeof("SIGNAL\n") - 1); - sem_post(&sem); + barrier_wait(&barrier); } void* my_thread(void* arg) { @@ -28,7 +27,11 @@ void* my_thread(void* arg) { } int main() { - sem_init(&sem, 0, 0); + barrier_init(&barrier, 2); + + pthread_mutex_init(&mutex, 0); + pthread_cond_init(&cond, 0); + signal(SIGUSR1, &sig_handler); pthread_t thr; pthread_create(&thr, 0, &my_thread, 0); @@ -36,8 +39,7 @@ int main() { // (can't use barrier_wait for that) sleep(1); pthread_kill(thr, SIGUSR1); - while (sem_wait(&sem) == -1 && errno == EINTR) { - } + barrier_wait(&barrier); pthread_mutex_lock(&mutex); g_thread_run = 0; pthread_cond_signal(&cond); diff --git a/src/compiler-rt/test/tsan/signal_errno.cc b/src/compiler-rt/test/tsan/signal_errno.cc index 5354cdeeb7..e13e156fdf 100644 --- a/src/compiler-rt/test/tsan/signal_errno.cc +++ b/src/compiler-rt/test/tsan/signal_errno.cc @@ -1,4 +1,8 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// This test fails on powerpc64 BE (VMA=44), it does not appear to be +// a functional problem, but the Tsan report is missing some info. +// XFAIL: powerpc64-unknown-linux-gnu + #include "test.h" #include #include diff --git a/src/compiler-rt/test/tsan/signal_longjmp.cc b/src/compiler-rt/test/tsan/signal_longjmp.cc index c02917f49f..45e24626cb 100644 --- a/src/compiler-rt/test/tsan/signal_longjmp.cc +++ b/src/compiler-rt/test/tsan/signal_longjmp.cc @@ -1,11 +1,14 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s // Test case for longjumping out of signal handler: -// https://code.google.com/p/thread-sanitizer/issues/detail?id=75 +// https://github.com/google/sanitizers/issues/482 -// Longjmp assembly has not been implemented for mips64 or aarch64 yet +// Longjmp assembly has not been implemented for mips64 yet // XFAIL: mips64 -// XFAIL: aarch64 +// This test fails on powerpc64 BE (VMA=44), a segmentation fault +// error happens at the second assignment +// "((volatile int *volatile)mem)[1] = 1". +// XFAIL: powerpc64-unknown-linux-gnu #include #include @@ -13,6 +16,12 @@ #include #include +#ifdef __APPLE__ +#define SIGNAL_TO_HANDLE SIGBUS +#else +#define SIGNAL_TO_HANDLE SIGSEGV +#endif + sigjmp_buf fault_jmp; volatile int fault_expected; @@ -45,7 +54,7 @@ int main() { exit(1); } - if (sigaction(SIGSEGV, &act, NULL)) { + if (sigaction(SIGNAL_TO_HANDLE, &act, NULL)) { perror("sigaction"); exit(1); } diff --git a/src/compiler-rt/test/tsan/signal_recursive.cc b/src/compiler-rt/test/tsan/signal_recursive.cc index 67fc9c0ec9..40be2d0150 100644 --- a/src/compiler-rt/test/tsan/signal_recursive.cc +++ b/src/compiler-rt/test/tsan/signal_recursive.cc @@ -1,7 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s // Test case for recursive signal handlers, adopted from: -// https://code.google.com/p/thread-sanitizer/issues/detail?id=71 +// https://github.com/google/sanitizers/issues/478 // REQUIRES: disabled diff --git a/src/compiler-rt/test/tsan/signal_reset.cc b/src/compiler-rt/test/tsan/signal_reset.cc index aec98dc399..82758d8823 100644 --- a/src/compiler-rt/test/tsan/signal_reset.cc +++ b/src/compiler-rt/test/tsan/signal_reset.cc @@ -1,4 +1,5 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include #include #include diff --git a/src/compiler-rt/test/tsan/signal_sync.cc b/src/compiler-rt/test/tsan/signal_sync.cc index 6ff19d3bd1..b529a1859f 100644 --- a/src/compiler-rt/test/tsan/signal_sync.cc +++ b/src/compiler-rt/test/tsan/signal_sync.cc @@ -1,4 +1,5 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include "test.h" #include #include diff --git a/src/compiler-rt/test/tsan/signal_thread.cc b/src/compiler-rt/test/tsan/signal_thread.cc index 8eda80a522..aa91d1ddeb 100644 --- a/src/compiler-rt/test/tsan/signal_thread.cc +++ b/src/compiler-rt/test/tsan/signal_thread.cc @@ -1,4 +1,5 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include #include #include diff --git a/src/compiler-rt/test/tsan/stack_sync_reuse.cc b/src/compiler-rt/test/tsan/stack_sync_reuse.cc index 5ea9e84b08..d2bc5cb1b2 100644 --- a/src/compiler-rt/test/tsan/stack_sync_reuse.cc +++ b/src/compiler-rt/test/tsan/stack_sync_reuse.cc @@ -1,7 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s #include "test.h" -// Test case https://code.google.com/p/thread-sanitizer/issues/detail?id=87 +// Test case https://github.com/google/sanitizers/issues/494 // Tsan sees false HB edge on address pointed to by syncp variable. // It is false because when acquire is done syncp points to a var in one frame, // and during release it points to a var in a different frame. @@ -31,7 +31,8 @@ void *Thread(void *x) { } void __attribute__((noinline)) foobar() { - long s; + __attribute__((aligned(64))) long s; + addr = &s; __atomic_store_n(&s, 0, __ATOMIC_RELAXED); __atomic_store_n(&syncp, &s, __ATOMIC_RELEASE); @@ -40,7 +41,8 @@ void __attribute__((noinline)) foobar() { } void __attribute__((noinline)) barfoo() { - long s; + __attribute__((aligned(64))) long s; + if (addr != &s) { printf("address mismatch addr=%p &s=%p\n", addr, &s); exit(1); diff --git a/src/compiler-rt/test/tsan/suppressions_global.cc b/src/compiler-rt/test/tsan/suppressions_global.cc index c7b9bb99eb..8928162cfb 100644 --- a/src/compiler-rt/test/tsan/suppressions_global.cc +++ b/src/compiler-rt/test/tsan/suppressions_global.cc @@ -1,4 +1,4 @@ -// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %run %t 2>&1 | FileCheck %s +// RUN: %clang_tsan -O1 %s -o %t && %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s #include #include diff --git a/src/compiler-rt/test/tsan/suppressions_race.cc b/src/compiler-rt/test/tsan/suppressions_race.cc index 45c30481f0..7a88434db8 100644 --- a/src/compiler-rt/test/tsan/suppressions_race.cc +++ b/src/compiler-rt/test/tsan/suppressions_race.cc @@ -1,4 +1,4 @@ -// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %run %t 2>&1 | FileCheck %s +// RUN: %clang_tsan -O1 %s -o %t && %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s #include "test.h" int Global; diff --git a/src/compiler-rt/test/tsan/suppressions_race2.cc b/src/compiler-rt/test/tsan/suppressions_race2.cc index 24ecd8ef11..b6566a8017 100644 --- a/src/compiler-rt/test/tsan/suppressions_race2.cc +++ b/src/compiler-rt/test/tsan/suppressions_race2.cc @@ -1,4 +1,4 @@ -// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="$TSAN_OPTIONS suppressions='%s.supp'" %run %t 2>&1 | FileCheck %s +// RUN: %clang_tsan -O1 %s -o %t && %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s #include "test.h" int Global; diff --git a/src/compiler-rt/test/tsan/test.h b/src/compiler-rt/test/tsan/test.h index adc44bbe96..a681daa329 100644 --- a/src/compiler-rt/test/tsan/test.h +++ b/src/compiler-rt/test/tsan/test.h @@ -4,56 +4,66 @@ #include #include #include +#include +#include + +#ifdef __APPLE__ +#include +#endif // TSan-invisible barrier. // Tests use it to establish necessary execution order in a way that does not // interfere with tsan (does not establish synchronization between threads). -// 8 lsb is thread count, the remaining are count of entered threads. typedef unsigned long long invisible_barrier_t; -void barrier_init(invisible_barrier_t *barrier, unsigned count) { - if (count >= (1 << 8)) - exit(fprintf(stderr, "barrier_init: count is too large (%d)\n", count)); - *barrier = count; +#ifdef __cplusplus +extern "C" { +#endif +void __tsan_testonly_barrier_init(invisible_barrier_t *barrier, + unsigned count); +void __tsan_testonly_barrier_wait(invisible_barrier_t *barrier); +#ifdef __cplusplus } +#endif -void barrier_wait(invisible_barrier_t *barrier) { - unsigned old = __atomic_fetch_add(barrier, 1 << 8, __ATOMIC_RELAXED); - unsigned old_epoch = (old >> 8) / (old & 0xff); - for (;;) { - unsigned cur = __atomic_load_n(barrier, __ATOMIC_RELAXED); - unsigned cur_epoch = (cur >> 8) / (cur & 0xff); - if (cur_epoch != old_epoch) - return; - usleep(1000); - } +static inline void barrier_init(invisible_barrier_t *barrier, unsigned count) { + __tsan_testonly_barrier_init(barrier, count); +} + +static inline void barrier_wait(invisible_barrier_t *barrier) { + __tsan_testonly_barrier_wait(barrier); } // Default instance of the barrier, but a test can declare more manually. invisible_barrier_t barrier; -void print_address(void *address) { -// On FreeBSD, the %p conversion specifier works as 0x%x and thus does not match -// to the format used in the diagnotic message. -#ifdef __x86_64__ - fprintf(stderr, "0x%012lx", (unsigned long) address); +void print_address(const char *str, int n, ...) { + fprintf(stderr, "%s", str); + va_list ap; + va_start(ap, n); + while (n--) { + void *p = va_arg(ap, void *); +#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) + // On FreeBSD, the %p conversion specifier works as 0x%x and thus does not + // match to the format used in the diagnotic message. + fprintf(stderr, "0x%012lx ", (unsigned long) p); #elif defined(__mips64) - fprintf(stderr, "0x%010lx", (unsigned long) address); -#elif defined(__aarch64__) - // AArch64 currently has 3 different VMA (39, 42, and 48 bits) and it requires - // different pointer size to match the diagnostic message. - const char *format = 0; - unsigned long vma = (unsigned long)__builtin_frame_address(0); - vma = 64 - __builtin_clzll(vma); - if (vma == 39) - format = "0x%010lx"; - else if (vma == 42) - format = "0x%011lx"; - else { - fprintf(stderr, "unsupported vma: %ul\n", vma); - exit(1); + fprintf(stderr, "0x%010lx ", (unsigned long) p); +#endif } + fprintf(stderr, "\n"); +} - fprintf(stderr, format, (unsigned long) address); -#endif +#ifdef __APPLE__ +unsigned long long monotonic_clock_ns() { + static mach_timebase_info_data_t timebase_info; + if (timebase_info.denom == 0) mach_timebase_info(&timebase_info); + return (mach_absolute_time() * timebase_info.numer) / timebase_info.denom; +} +#else +unsigned long long monotonic_clock_ns() { + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return (unsigned long long)t.tv_sec * 1000000000ull + t.tv_nsec; } +#endif diff --git a/src/compiler-rt/test/tsan/test_output.sh b/src/compiler-rt/test/tsan/test_output.sh deleted file mode 100755 index bce0fe8b55..0000000000 --- a/src/compiler-rt/test/tsan/test_output.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -ulimit -s 8192 -set -e # fail on any error - -HERE=$(dirname $0) -TSAN_DIR=$(dirname $0)/../../lib/tsan - -# Assume clang and clang++ are in path. -: ${CC:=clang} -: ${CXX:=clang++} -: ${FILECHECK:=FileCheck} - -# TODO: add testing for all of -O0...-O3 -CFLAGS="-fsanitize=thread -O2 -g -Wall" -LDFLAGS="-pthread -ldl -lrt -lm -Wl,--whole-archive $TSAN_DIR/rtl/libtsan.a -Wl,--no-whole-archive" - -test_file() { - SRC=$1 - COMPILER=$2 - echo ----- TESTING $(basename $1) - OBJ=$SRC.o - EXE=$SRC.exe - $COMPILER $SRC $CFLAGS -c -o $OBJ - $COMPILER $OBJ $LDFLAGS -o $EXE - RES=$($EXE 2>&1 || true) - printf "%s\n" "$RES" | $FILECHECK $SRC - if [ "$3" == "" ]; then - rm -f $EXE $OBJ - fi -} - -if [ "$1" == "" ]; then - for c in $HERE/*.{c,cc}; do - if [[ $c == */failing_* ]]; then - echo SKIPPING FAILING TEST $c - continue - fi - if [[ $c == */load_shared_lib.cc ]]; then - echo TEST $c is not supported - continue - fi - if [[ $c == */*blacklist*.cc ]]; then - echo TEST $c is not supported - continue - fi - if [ "`grep "TSAN_OPTIONS" $c`" ]; then - echo SKIPPING $c -- requires TSAN_OPTIONS - continue - fi - if [ "`grep "XFAIL" $c`" ]; then - echo SKIPPING $c -- has XFAIL - continue - fi - COMPILER=$CXX - case $c in - *.c) COMPILER=$CC - esac - test_file $c $COMPILER & - done - for job in `jobs -p`; do - wait $job || exit 1 - done -else - test_file $HERE/$1 $CXX "DUMP" -fi diff --git a/src/compiler-rt/test/tsan/thread_name2.cc b/src/compiler-rt/test/tsan/thread_name2.cc index 93387dab2b..d7ed0f0d19 100644 --- a/src/compiler-rt/test/tsan/thread_name2.cc +++ b/src/compiler-rt/test/tsan/thread_name2.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s #include "test.h" +// OS X doesn't have pthread_setname_np(tid, name). +// UNSUPPORTED: darwin + #if defined(__FreeBSD__) #include #define pthread_setname_np pthread_set_name_np diff --git a/src/compiler-rt/test/tsan/tls_race.cc b/src/compiler-rt/test/tsan/tls_race.cc index 5e81722767..b43a514cc8 100644 --- a/src/compiler-rt/test/tsan/tls_race.cc +++ b/src/compiler-rt/test/tsan/tls_race.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK #include "test.h" void *Thread(void *a) { @@ -18,4 +18,6 @@ int main() { } // CHECK: WARNING: ThreadSanitizer: data race -// CHECK: Location is TLS of main thread. +// CHECK-Linux: Location is TLS of main thread. +// CHECK-FreeBSD: Location is TLS of main thread. +// CHECK-Darwin: Location is heap block of size 4 diff --git a/src/compiler-rt/test/tsan/tls_race2.cc b/src/compiler-rt/test/tsan/tls_race2.cc index d0f7b03e09..b04ff67881 100644 --- a/src/compiler-rt/test/tsan/tls_race2.cc +++ b/src/compiler-rt/test/tsan/tls_race2.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK #include "test.h" void *Thread2(void *a) { @@ -25,5 +25,6 @@ int main() { } // CHECK: WARNING: ThreadSanitizer: data race -// CHECK: Location is TLS of thread T1. - +// CHECK-Linux: Location is TLS of thread T1. +// CHECK-FreeBSD: Location is TLS of thread T1. +// CHECK-Darwin: Location is heap block of size 4 diff --git a/src/compiler-rt/test/tsan/vfork.cc b/src/compiler-rt/test/tsan/vfork.cc index 5ae1dd1aba..98a82623ee 100644 --- a/src/compiler-rt/test/tsan/vfork.cc +++ b/src/compiler-rt/test/tsan/vfork.cc @@ -1,4 +1,5 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: darwin #include #include #include diff --git a/src/compiler-rt/test/tsan/virtual_inheritance_compile_bug.cc b/src/compiler-rt/test/tsan/virtual_inheritance_compile_bug.cc index 2a50c2e88d..7da581d806 100644 --- a/src/compiler-rt/test/tsan/virtual_inheritance_compile_bug.cc +++ b/src/compiler-rt/test/tsan/virtual_inheritance_compile_bug.cc @@ -1,4 +1,4 @@ -// Regression test for http://code.google.com/p/thread-sanitizer/issues/detail?id=3. +// Regression test for https://github.com/google/sanitizers/issues/410. // The C++ variant is much more compact that the LLVM IR equivalent. // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s diff --git a/src/compiler-rt/test/tsan/vptr_benign_race.cc b/src/compiler-rt/test/tsan/vptr_benign_race.cc index 92a2b326e7..c006895512 100644 --- a/src/compiler-rt/test/tsan/vptr_benign_race.cc +++ b/src/compiler-rt/test/tsan/vptr_benign_race.cc @@ -1,28 +1,36 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s #include -#include #include struct A { A() { - sem_init(&sem_, 0, 0); + pthread_mutex_init(&m, 0); + pthread_cond_init(&c, 0); + signaled = false; } virtual void F() { } void Done() { - sem_post(&sem_); + pthread_mutex_lock(&m); + signaled = true; + pthread_cond_signal(&c); + pthread_mutex_unlock(&m); } virtual ~A() { } - sem_t sem_; + pthread_mutex_t m; + pthread_cond_t c; + bool signaled; }; struct B : A { virtual void F() { } virtual ~B() { - sem_wait(&sem_); - sem_destroy(&sem_); + pthread_mutex_lock(&m); + while (!signaled) + pthread_cond_wait(&c, &m); + pthread_mutex_unlock(&m); } }; diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/summary.cpp b/src/compiler-rt/test/ubsan/TestCases/Integer/summary.cpp index 5843236922..e687afab43 100644 --- a/src/compiler-rt/test/ubsan/TestCases/Integer/summary.cpp +++ b/src/compiler-rt/test/ubsan/TestCases/Integer/summary.cpp @@ -1,5 +1,5 @@ // RUN: %clangxx -fsanitize=integer %s -o %t -// RUN: %t 2>&1 | FileCheck %s --check-prefix=CHECK-NOTYPE +// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NOTYPE // RUN: %env_ubsan_opts=report_error_type=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-TYPE // REQUIRES: ubsan-asan diff --git a/src/compiler-rt/test/ubsan/TestCases/Integer/suppressions.cpp b/src/compiler-rt/test/ubsan/TestCases/Integer/suppressions.cpp new file mode 100644 index 0000000000..e6ae626db3 --- /dev/null +++ b/src/compiler-rt/test/ubsan/TestCases/Integer/suppressions.cpp @@ -0,0 +1,33 @@ +// RUN: %clangxx -fsanitize=integer -g0 %s -o %t + +// Fails without any suppression. +// RUN: %env_ubsan_opts=halt_on_error=1 not %run %t 2>&1 | FileCheck %s + +// RUN: echo "signed-integer-overflow:%t" > %t.wrong-supp +// RUN: %env_ubsan_opts=halt_on_error=1:suppressions='"%t.wrong-supp"' not %run %t 2>&1 | FileCheck %s + +// RUN: echo "unsigned-integer-overflow:do_overflow" > %t.func-supp +// RUN: %env_ubsan_opts=halt_on_error=1:suppressions='"%t.func-supp"' %run %t +// RUN: echo "unsigned-integer-overflow:%t" > %t.module-supp +// RUN: %env_ubsan_opts=halt_on_error=1:suppressions='"%t.module-supp"' %run %t + +// Note: file-level suppressions should work even without debug info. +// RUN: echo "unsigned-integer-overflow:%s" > %t.file-supp +// RUN: %env_ubsan_opts=halt_on_error=1:suppressions='"%t.file-supp"' %run %t + +// Suppressions don't work for unrecoverable kinds. +// RUN: %clangxx -fsanitize=integer -fno-sanitize-recover=integer %s -o %t-norecover +// RUN: %env_ubsan_opts=halt_on_error=1:suppressions='"%t.module-supp"' not %run %t-norecover 2>&1 | FileCheck %s + +#include + +extern "C" void do_overflow() { + (void)(uint64_t(10000000000000000000ull) + uint64_t(9000000000000000000ull)); + // CHECK: runtime error: unsigned integer overflow +} + +int main() { + do_overflow(); + return 0; +} + diff --git a/src/compiler-rt/test/ubsan/TestCases/Misc/Linux/ubsan_options.cc b/src/compiler-rt/test/ubsan/TestCases/Misc/Linux/ubsan_options.cc index 2be8792cce..eac4c32a28 100644 --- a/src/compiler-rt/test/ubsan/TestCases/Misc/Linux/ubsan_options.cc +++ b/src/compiler-rt/test/ubsan/TestCases/Misc/Linux/ubsan_options.cc @@ -1,5 +1,5 @@ // RUN: %clangxx -fsanitize=integer -fsanitize-recover=integer %s -o %t -// RUN: not %t 2>&1 | FileCheck %s +// RUN: not %run %t 2>&1 | FileCheck %s // __ubsan_default_options() doesn't work on Darwin. // XFAIL: darwin diff --git a/src/compiler-rt/test/ubsan/lit.common.cfg b/src/compiler-rt/test/ubsan/lit.common.cfg index 8e84406664..e50862983d 100644 --- a/src/compiler-rt/test/ubsan/lit.common.cfg +++ b/src/compiler-rt/test/ubsan/lit.common.cfg @@ -42,6 +42,7 @@ if config.host_os == 'Darwin': # On Darwin, we default to `abort_on_error=1`, which would make tests run # much slower. Let's override this and run lit tests with 'abort_on_error=0'. default_ubsan_opts += ['abort_on_error=0'] + default_ubsan_opts += ['log_to_syslog=0'] default_ubsan_opts_str = ':'.join(default_ubsan_opts) if default_ubsan_opts_str: config.environment['UBSAN_OPTIONS'] = default_ubsan_opts_str diff --git a/src/doc/book/advanced-linking.md b/src/doc/book/advanced-linking.md index c8a9082947..ddaebaf98d 100644 --- a/src/doc/book/advanced-linking.md +++ b/src/doc/book/advanced-linking.md @@ -134,7 +134,7 @@ $ ldd example not a dynamic executable $ ./example hi! -thread '
' panicked at 'failed', example.rs:1 +thread 'main' panicked at 'failed', example.rs:1 ``` Success! This binary can be copied to almost any Linux machine with the same diff --git a/src/doc/book/choosing-your-guarantees.md b/src/doc/book/choosing-your-guarantees.md index 5035021307..d88f619260 100644 --- a/src/doc/book/choosing-your-guarantees.md +++ b/src/doc/book/choosing-your-guarantees.md @@ -232,7 +232,7 @@ indicator (one word in size) along with the data. At runtime each borrow causes a modification/check of the refcount. -[cell-mod]: ../std/cell/ +[cell-mod]: ../std/cell/index.html [cell]: ../std/cell/struct.Cell.html [refcell]: ../std/cell/struct.RefCell.html diff --git a/src/doc/book/closures.md b/src/doc/book/closures.md index dedf9d5c28..a6b4e94921 100644 --- a/src/doc/book/closures.md +++ b/src/doc/book/closures.md @@ -322,7 +322,7 @@ to our closure when we pass it to `call_with_one`, so we use `&||`. A quick note about closures that use explicit lifetimes. Sometimes you might have a closure that takes a reference like so: -``` +```rust fn call_with_ref(some_closure:F) -> i32 where F: Fn(&i32) -> i32 { @@ -334,8 +334,8 @@ fn call_with_ref(some_closure:F) -> i32 Normally you can specify the lifetime of the parameter to our closure. We could annotate it on the function declaration: -```ignore -fn call_with_ref<'a, F>(some_closure:F) -> i32 +```rust,ignore +fn call_with_ref<'a, F>(some_closure:F) -> i32 where F: Fn(&'a 32) -> i32 { ``` @@ -353,11 +353,11 @@ fn call_with_ref(some_closure:F) -> i32 where F: for<'a> Fn(&'a 32) -> i32 { ``` -This lets the Rust compiler find the minimum lifetime to invoke our closure and +This lets the Rust compiler find the minimum lifetime to invoke our closure and satisfy the borrow checker's rules. Our function then compiles and excutes as we expect. -``` +```rust fn call_with_ref(some_closure:F) -> i32 where F: for<'a> Fn(&'a i32) -> i32 { diff --git a/src/doc/book/compiler-plugins.md b/src/doc/book/compiler-plugins.md index 2d0cc61fb1..8426d5a626 100644 --- a/src/doc/book/compiler-plugins.md +++ b/src/doc/book/compiler-plugins.md @@ -34,7 +34,7 @@ code that manipulates syntax trees at compile time. Let's write a plugin -[`roman_numerals.rs`](https://github.com/rust-lang/rust/tree/master/src/test/auxiliary/roman_numerals.rs) +[`roman_numerals.rs`](https://github.com/rust-lang/rust/blob/master/src/test/run-pass-fulldeps/auxiliary/roman_numerals.rs) that implements Roman numeral integer literals. ```rust,ignore @@ -45,11 +45,11 @@ extern crate syntax; extern crate rustc; extern crate rustc_plugin; -use syntax::codemap::Span; use syntax::parse::token; use syntax::ast::TokenTree; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax::ext::build::AstBuilder; // trait for expr_usize +use syntax_pos::Span; use rustc_plugin::Registry; fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) @@ -166,7 +166,8 @@ quasiquote as an ordinary plugin library. Plugins can extend [Rust's lint infrastructure](../reference.html#lint-check-attributes) with additional checks for -code style, safety, etc. Now let's write a plugin [`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/auxiliary/lint_plugin_test.rs) +code style, safety, etc. Now let's write a plugin +[`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/run-pass-fulldeps/auxiliary/lint_plugin_test.rs) that warns about any item named `lintme`. ```rust,ignore diff --git a/src/doc/book/crates-and-modules.md b/src/doc/book/crates-and-modules.md index 43ac30c35c..67fe8ba2c1 100644 --- a/src/doc/book/crates-and-modules.md +++ b/src/doc/book/crates-and-modules.md @@ -22,12 +22,10 @@ As an example, let’s make a *phrases* crate, which will give us various phrase in different languages. To keep things simple, we’ll stick to ‘greetings’ and ‘farewells’ as two kinds of phrases, and use English and Japanese (日本語) as two languages for those phrases to be in. We’ll use this module layout: - ```text +-----------+ +---| greetings | - | +-----------+ - +---------+ | + +---------+ | +-----------+ +---| english |---+ | +---------+ | +-----------+ | +---| farewells | @@ -37,8 +35,7 @@ two languages for those phrases to be in. We’ll use this module layout: | +---| greetings | | +----------+ | +-----------+ +---| japanese |--+ - +----------+ | - | +-----------+ + +----------+ | +-----------+ +---| farewells | +-----------+ ``` diff --git a/src/doc/book/documentation.md b/src/doc/book/documentation.md index 4a41bb7b7f..3c6643fbfe 100644 --- a/src/doc/book/documentation.md +++ b/src/doc/book/documentation.md @@ -76,7 +76,7 @@ This [unfortunate error](https://github.com/rust-lang/rust/issues/22547) is correct; documentation comments apply to the thing after them, and there's nothing after that last comment. -[rc-new]: https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new +[rc-new]: ../std/rc/struct.Rc.html#method.new ### Writing documentation comments diff --git a/src/doc/book/error-handling.md b/src/doc/book/error-handling.md index c914c33a5a..544f837d69 100644 --- a/src/doc/book/error-handling.md +++ b/src/doc/book/error-handling.md @@ -81,7 +81,7 @@ fn main() { If you try running this code, the program will crash with a message like this: ```text -thread '
' panicked at 'Invalid number: 11', src/bin/panic-simple.rs:5 +thread 'main' panicked at 'Invalid number: 11', src/bin/panic-simple.rs:5 ``` Here's another example that is slightly less contrived. A program that accepts @@ -498,7 +498,7 @@ At this point, you should be skeptical of calling `unwrap`. For example, if the string doesn't parse as a number, you'll get a panic: ```text -thread '
' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }', /home/rustbuild/src/rust-buildbot/slave/beta-dist-rustc-linux/build/src/libcore/result.rs:729 +thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }', /home/rustbuild/src/rust-buildbot/slave/beta-dist-rustc-linux/build/src/libcore/result.rs:729 ``` This is rather unsightly, and if this happened inside a library you're @@ -1829,7 +1829,7 @@ use std::error::Error; fn search> (file_path: P, city: &str) - -> Result, Box> { + -> Result, Box> { let mut found = vec![]; let file = try!(File::open(file_path)); let mut rdr = csv::Reader::from_reader(file); @@ -1858,20 +1858,17 @@ Instead of `x.unwrap()`, we now have `try!(x)`. Since our function returns a `Result`, the `try!` macro will return early from the function if an error occurs. -There is one big gotcha in this code: we used `Box` -instead of `Box`. We did this so we could convert a plain string to an -error type. We need these extra bounds so that we can use the -[corresponding `From` -impls](../std/convert/trait.From.html): +At the end of `search` we also convert a plain string to an error type +by using the [corresponding `From` impls](../std/convert/trait.From.html): ```rust,ignore // We are making use of this impl in the code above, since we call `From::from` // on a `&'static str`. -impl<'a, 'b> From<&'b str> for Box +impl<'a> From<&'a str> for Box // But this is also useful when you need to allocate a new string for an // error message, usually with `format!`. -impl From for Box +impl From for Box ``` Since `search` now returns a `Result`, `main` should use case analysis @@ -1964,7 +1961,7 @@ use std::io; fn search> (file_path: &Option

, city: &str) - -> Result, Box> { + -> Result, Box> { let mut found = vec![]; let input: Box = match *file_path { None => Box::new(io::stdin()), @@ -2175,9 +2172,8 @@ heuristics! `unwrap`. Be warned: if it winds up in someone else's hands, don't be surprised if they are agitated by poor error messages! * If you're writing a quick 'n' dirty program and feel ashamed about panicking - anyway, then use either a `String` or a `Box` for your - error type (the `Box` type is because of the - [available `From` impls](../std/convert/trait.From.html)). + anyway, then use either a `String` or a `Box` for your + error type. * Otherwise, in a program, define your own error types with appropriate [`From`](../std/convert/trait.From.html) and @@ -2205,7 +2201,7 @@ heuristics! [3]: ../std/option/enum.Option.html#method.unwrap_or [4]: ../std/option/enum.Option.html#method.unwrap_or_else [5]: ../std/option/enum.Option.html -[6]: ../std/result/ +[6]: ../std/result/index.html [7]: ../std/result/enum.Result.html#method.unwrap [8]: ../std/fmt/trait.Debug.html [9]: ../std/primitive.str.html#method.parse diff --git a/src/doc/book/functions.md b/src/doc/book/functions.md index 3a10d2aecc..b040684d05 100644 --- a/src/doc/book/functions.md +++ b/src/doc/book/functions.md @@ -221,7 +221,7 @@ If you add a main function that calls `diverges()` and run it, you’ll get some output that looks like this: ```text -thread ‘

’ panicked at ‘This function never returns!’, hello.rs:2 +thread ‘main’ panicked at ‘This function never returns!’, hello.rs:2 ``` If you want more information, you can get a backtrace by setting the @@ -229,7 +229,7 @@ If you want more information, you can get a backtrace by setting the ```text $ RUST_BACKTRACE=1 ./diverges -thread '
' panicked at 'This function never returns!', hello.rs:2 +thread 'main' panicked at 'This function never returns!', hello.rs:2 stack backtrace: 1: 0x7f402773a829 - sys::backtrace::write::h0942de78b6c02817K8r 2: 0x7f402773d7fc - panicking::on_panic::h3f23f9d0b5f4c91bu9w @@ -249,13 +249,13 @@ stack backtrace: If you need to override an already set `RUST_BACKTRACE`, in cases when you cannot just unset the variable, then set it to `0` to avoid getting a backtrace. -Any other value(even no value at all) turns on backtrace. +Any other value (even no value at all) turns on backtrace. ```text $ export RUST_BACKTRACE=1 ... $ RUST_BACKTRACE=0 ./diverges -thread '
' panicked at 'This function never returns!', hello.rs:2 +thread 'main' panicked at 'This function never returns!', hello.rs:2 note: Run with `RUST_BACKTRACE=1` for a backtrace. ``` @@ -264,7 +264,7 @@ note: Run with `RUST_BACKTRACE=1` for a backtrace. ```text $ RUST_BACKTRACE=1 cargo run Running `target/debug/diverges` -thread '
' panicked at 'This function never returns!', hello.rs:2 +thread 'main' panicked at 'This function never returns!', hello.rs:2 stack backtrace: 1: 0x7f402773a829 - sys::backtrace::write::h0942de78b6c02817K8r 2: 0x7f402773d7fc - panicking::on_panic::h3f23f9d0b5f4c91bu9w diff --git a/src/doc/book/glossary.md b/src/doc/book/glossary.md index 0956580ade..8aa7fdff94 100644 --- a/src/doc/book/glossary.md +++ b/src/doc/book/glossary.md @@ -46,6 +46,12 @@ must abide by that constraint. [traits]: traits.html +### Combinators + +Combinators are higher-order functions that apply only functions and +earlier defined combinators to provide a result from its arguments. +They can be used to manage control flow in a modular fashion. + ### DST (Dynamically Sized Type) A type without a statically known size or alignment. ([more info][link]) diff --git a/src/doc/book/guessing-game.md b/src/doc/book/guessing-game.md index a2067e33a6..c759ff9bdb 100644 --- a/src/doc/book/guessing-game.md +++ b/src/doc/book/guessing-game.md @@ -806,7 +806,7 @@ You guessed: 59 You win! Please input your guess. quit -thread '
' panicked at 'Please type a number!' +thread 'main' panicked at 'Please type a number!' ``` Ha! `quit` actually quits. As does any other non-number input. Well, this is diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md index cb07573189..f7d9c94bc4 100644 --- a/src/doc/book/lifetimes.md +++ b/src/doc/book/lifetimes.md @@ -290,7 +290,7 @@ lifetime parameters using three easily memorizable and unambiguous rules. This m acts as a shorthand for writing an item signature, while not hiding away the actual types involved as full local inference would if applied to it. -When talking about lifetime elision, we use the term *input lifetime* and +When talking about lifetime elision, we use the terms *input lifetime* and *output lifetime*. An *input lifetime* is a lifetime associated with a parameter of a function, and an *output lifetime* is a lifetime associated with the return value of a function. For example, this function has an input lifetime: @@ -335,11 +335,13 @@ fn print<'a>(s: &'a str); // expanded fn debug(lvl: u32, s: &str); // elided fn debug<'a>(lvl: u32, s: &'a str); // expanded +``` -// In the preceding example, `lvl` doesn’t need a lifetime because it’s not a -// reference (`&`). Only things relating to references (such as a `struct` -// which contains a reference) need lifetimes. +In the preceding example, `lvl` doesn’t need a lifetime because it’s not a +reference (`&`). Only things relating to references (such as a `struct` +which contains a reference) need lifetimes. +```rust,ignore fn substr(s: &str, until: u32) -> &str; // elided fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded diff --git a/src/doc/book/loops.md b/src/doc/book/loops.md index 97ca2e3e70..e23e6f3a78 100644 --- a/src/doc/book/loops.md +++ b/src/doc/book/loops.md @@ -178,7 +178,7 @@ loop { We now loop forever with `loop` and use `break` to break out early. Issuing an explicit `return` statement will also serve to terminate the loop early. -`continue` is similar, but instead of ending the loop, goes to the next +`continue` is similar, but instead of ending the loop, it goes to the next iteration. This will only print the odd numbers: ```rust diff --git a/src/doc/book/no-stdlib.md b/src/doc/book/no-stdlib.md index 43bd0507eb..c5c139e658 100644 --- a/src/doc/book/no-stdlib.md +++ b/src/doc/book/no-stdlib.md @@ -12,9 +12,26 @@ don’t want to use the standard library via an attribute: `#![no_std]`. > `#![no_std]`](using-rust-without-the-standard-library.html) Obviously there's more to life than just libraries: one can use -`#[no_std]` with an executable, controlling the entry point is -possible in two ways: the `#[start]` attribute, or overriding the -default shim for the C `main` function with your own. +`#[no_std]` with an executable. + +### Using libc + +In order to build a `#[no_std]` executable we will need libc as a dependency. We can specify +this using our `Cargo.toml` file: + +```toml +[dependencies] +libc = { version = "0.2.11", default-features = false } +``` + +Note that the default features have been disabled. This is a critical step - +**the default features of libc include the standard library and so must be +disabled.** + +### Writing an executable without stdlib + +Controlling the entry point is possible in two ways: the `#[start]` attribute, +or overriding the default shim for the C `main` function with your own. The function marked `#[start]` is passed the command line parameters in the same format as C: @@ -72,7 +89,6 @@ pub extern fn main(argc: i32, argv: *const *const u8) -> i32 { # // fn main() {} tricked you, rustdoc! ``` - The compiler currently makes a few assumptions about symbols which are available in the executable to call. Normally these functions are provided by the standard library, but without it you must define your own. @@ -84,4 +100,4 @@ which do not trigger a panic can be assured that this function is never called. The second function, `panic_fmt`, is also used by the failure mechanisms of the compiler. -[unwind]: https://github.com/rust-lang/rust/blob/master/src/libstd/sys/common/unwind/gcc.rs +[unwind]: https://github.com/rust-lang/rust/blob/master/src/libpanic_unwind/gcc.rs diff --git a/src/doc/book/ownership.md b/src/doc/book/ownership.md index f445bed015..23ca21b3b4 100644 --- a/src/doc/book/ownership.md +++ b/src/doc/book/ownership.md @@ -67,7 +67,7 @@ Vectors have a [generic type][generics] `Vec`, so in this example `v` will ha [arrays]: primitive-types.html#arrays [vectors]: vectors.html -[heap]: the-stack-and-the-heap.html +[heap]: the-stack-and-the-heap.html#the-heap [stack]: the-stack-and-the-heap.html#the-stack [bindings]: variable-bindings.html [generics]: generics.html @@ -136,6 +136,8 @@ Rust allocates memory for an integer [i32] on the [stack][sh], copies the bit pattern representing the value of 10 to the allocated memory and binds the variable name x to this memory region for future reference. +[i32]: primitive-types.html#numeric-types + Now consider the following code fragment: ```rust @@ -212,7 +214,7 @@ But, unlike a move, we can still use `v` afterward. This is because an `i32` has no pointers to data somewhere else, copying it is a full copy. All primitive types implement the `Copy` trait and their ownership is -therefore not moved like one would assume, following the ´ownership rules´. +therefore not moved like one would assume, following the ‘ownership rules’. To give an example, the two following snippets of code only compile because the `i32` and `bool` types implement the `Copy` trait. @@ -288,6 +290,6 @@ let (v1, v2, answer) = foo(v1, v2); Ugh! The return type, return line, and calling the function gets way more complicated. -Luckily, Rust offers a feature, borrowing, which helps us solve this problem. -It’s the topic of the next section! +Luckily, Rust offers a feature which helps us solve this problem. +It’s called borrowing and is the topic of the next section! diff --git a/src/doc/book/patterns.md b/src/doc/book/patterns.md index 7ecfdcfcc1..a0245d4c7b 100644 --- a/src/doc/book/patterns.md +++ b/src/doc/book/patterns.md @@ -174,7 +174,7 @@ Here, we bind the first and last element of the tuple to `x` and `z`, but ignore the middle element. It’s worth noting that using `_` never binds the value in the first place, -which means a value may not move: +which means that the value does not move: ```rust let tuple: (u32, String) = (5, String::from("five")); diff --git a/src/doc/book/primitive-types.md b/src/doc/book/primitive-types.md index 2a4b7ba37f..ea0bdf29fc 100644 --- a/src/doc/book/primitive-types.md +++ b/src/doc/book/primitive-types.md @@ -163,7 +163,7 @@ A ‘slice’ is a reference to (or “view” into) another data structure. The useful for allowing safe, efficient access to a portion of an array without copying. For example, you might want to reference only one line of a file read into memory. By nature, a slice is not created directly, but from an existing -variable binding. Slices have a defined length, can be mutable or immutable. +variable binding. Slices have a defined length, and can be mutable or immutable. Internally, slices are represented as a pointer to the beginning of the data and a length. @@ -175,8 +175,6 @@ You can use a combo of `&` and `[]` to create a slice from various things. The detail later in this section. The `[]`s, with a range, let you define the length of the slice: -[references]: references-and-borrowing.html - ```rust let a = [0, 1, 2, 3, 4]; let complete = &a[..]; // A slice containing all of the elements in a diff --git a/src/doc/book/references-and-borrowing.md b/src/doc/book/references-and-borrowing.md index a28f450c94..57bfbce8b8 100644 --- a/src/doc/book/references-and-borrowing.md +++ b/src/doc/book/references-and-borrowing.md @@ -85,7 +85,7 @@ fn main() { fn sum_vec(v: &Vec) -> i32 { return v.iter().fold(0, |a, &b| a + b); } - // Borrow two vectors and and sum them. + // Borrow two vectors and sum them. // This kind of borrowing does not allow mutation to the borrowed. fn foo(v1: &Vec, v2: &Vec) -> i32 { // do stuff with v1 and v2 @@ -123,7 +123,7 @@ let v = vec![]; foo(&v); ``` -errors with: +will give us this error: ```text error: cannot borrow immutable borrowed content `*v` as mutable @@ -152,8 +152,8 @@ the thing `y` points at. You’ll notice that `x` had to be marked `mut` as well If it wasn’t, we couldn’t take a mutable borrow to an immutable value. You'll also notice we added an asterisk (`*`) in front of `y`, making it `*y`, -this is because `y` is a `&mut` reference. You'll also need to use them for -accessing the contents of a reference as well. +this is because `y` is a `&mut` reference. You'll need to use astrisks to +access the contents of a reference as well. Otherwise, `&mut` references are like references. There _is_ a large difference between the two, and how they interact, though. You can tell @@ -179,7 +179,7 @@ As it turns out, there are rules. # The Rules -Here’s the rules about borrowing in Rust: +Here are the rules for borrowing in Rust: First, any borrow must last for a scope no greater than that of the owner. Second, you may have one or the other of these two kinds of borrows, but not @@ -208,12 +208,14 @@ With this in mind, let’s consider our example again. Here’s the code: ```rust,ignore -let mut x = 5; -let y = &mut x; +fn main() { + let mut x = 5; + let y = &mut x; -*y += 1; + *y += 1; -println!("{}", x); + println!("{}", x); +} ``` This code gives us this error: @@ -225,7 +227,7 @@ error: cannot borrow `x` as immutable because it is also borrowed as mutable ``` This is because we’ve violated the rules: we have a `&mut T` pointing to `x`, -and so we aren’t allowed to create any `&T`s. One or the other. The note +and so we aren’t allowed to create any `&T`s. It's one or the other. The note hints at how to think about this problem: ```text @@ -243,14 +245,16 @@ In Rust, borrowing is tied to the scope that the borrow is valid for. And our scopes look like this: ```rust,ignore -let mut x = 5; - -let y = &mut x; // -+ &mut borrow of x starts here - // | -*y += 1; // | - // | -println!("{}", x); // -+ - try to borrow x here - // -+ &mut borrow of x ends here +fn main() { + let mut x = 5; + + let y = &mut x; // -+ &mut borrow of x starts here + // | + *y += 1; // | + // | + println!("{}", x); // -+ - try to borrow x here +} // -+ &mut borrow of x ends here + ``` The scopes conflict: we can’t make an `&x` while `y` is in scope. @@ -269,12 +273,12 @@ println!("{}", x); // <- try to borrow x here ``` There’s no problem. Our mutable borrow goes out of scope before we create an -immutable one. But scope is the key to seeing how long a borrow lasts for. +immutable one. So scope is the key to seeing how long a borrow lasts for. ## Issues borrowing prevents Why have these restrictive rules? Well, as we noted, these rules prevent data -races. What kinds of issues do data races cause? Here’s a few. +races. What kinds of issues do data races cause? Here are a few. ### Iterator invalidation @@ -323,7 +327,7 @@ for i in &v { We can’t modify `v` because it’s borrowed by the loop. -### use after free +### Use after free References must not live longer than the resource they refer to. Rust will check the scopes of your references to ensure that this is true. diff --git a/src/doc/book/slice-patterns.md b/src/doc/book/slice-patterns.md index de165b70fc..fcedf0c994 100644 --- a/src/doc/book/slice-patterns.md +++ b/src/doc/book/slice-patterns.md @@ -10,7 +10,7 @@ fn main() { let v = vec!["match_this", "1"]; match &v[..] { - ["match_this", second] => println!("The second element is {}", second), + &["match_this", second] => println!("The second element is {}", second), _ => {}, } } @@ -26,8 +26,8 @@ slice will be bound to that name. For example: fn is_symmetric(list: &[u32]) -> bool { match list { - [] | [_] => true, - [x, inside.., y] if x == y => is_symmetric(inside), + &[] | &[_] => true, + &[x, ref inside.., y] if x == y => is_symmetric(inside), _ => false } } diff --git a/src/doc/book/strings.md b/src/doc/book/strings.md index 008644ec9a..7be90e785b 100644 --- a/src/doc/book/strings.md +++ b/src/doc/book/strings.md @@ -163,7 +163,7 @@ let hachi = &dog[0..2]; with this error: ```text -thread '
' panicked at 'index 0 and/or 2 in `忠犬ハチ公` do not lie on +thread 'main' panicked at 'index 0 and/or 2 in `忠犬ハチ公` do not lie on character boundary' ``` diff --git a/src/doc/book/testing.md b/src/doc/book/testing.md index 4ea114c4be..7954085472 100644 --- a/src/doc/book/testing.md +++ b/src/doc/book/testing.md @@ -107,7 +107,7 @@ failures: test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured -thread '
' panicked at 'Some tests failed', /home/steve/src/rust/src/libtest/lib.rs:247 +thread 'main' panicked at 'Some tests failed', /home/steve/src/rust/src/libtest/lib.rs:247 ``` Rust indicates that our test failed: @@ -380,8 +380,9 @@ the `tests` directory. # The `tests` directory -To write an integration test, let's make a `tests` directory, and -put a `tests/lib.rs` file inside, with this as its contents: +Each file in `tests/*.rs` directory is treated as individual crate. +So, to write an integration test, let's make a `tests` directory, and +put a `tests/integration_test.rs` file inside, with this as its contents: ```rust,ignore extern crate adder; @@ -394,8 +395,8 @@ fn it_works() { ``` This looks similar to our previous tests, but slightly different. We now have -an `extern crate adder` at the top. This is because the tests in the `tests` -directory are an entirely separate crate, and so we need to import our library. +an `extern crate adder` at the top. This is because each test in the `tests` +directory is an entirely separate crate, and so we need to import our library. This is also why `tests` is a suitable place to write integration-style tests: they use the library like any other consumer of it would. @@ -428,6 +429,11 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured Now we have three sections: our previous test is also run, as well as our new one. +Cargo will ignore files in subdirectories of the `tests/` directory. +Therefore shared modules in integrations tests are possible. +For example `tests/common/mod.rs` is not seperatly compiled by cargo but can +be imported in every test with `mod common;` + That's all there is to the `tests` directory. The `tests` module isn't needed here, since the whole thing is focused on tests. diff --git a/src/doc/book/traits.md b/src/doc/book/traits.md index 107ef2b44d..e685cb129b 100644 --- a/src/doc/book/traits.md +++ b/src/doc/book/traits.md @@ -397,10 +397,10 @@ fn normal>(x: &T) -> i64 { } // can be called with T == i64 -fn inverse() -> T +fn inverse(x: i32) -> T // this is using ConvertTo as if it were "ConvertTo" where i32: ConvertTo { - 42.convert() + x.convert() } ``` diff --git a/src/doc/book/using-rust-without-the-standard-library.md b/src/doc/book/using-rust-without-the-standard-library.md index 1179aebe54..69958dd3e6 100644 --- a/src/doc/book/using-rust-without-the-standard-library.md +++ b/src/doc/book/using-rust-without-the-standard-library.md @@ -22,11 +22,12 @@ fn plus_one(x: i32) -> i32 { ``` Much of the functionality that’s exposed in the standard library is also -available via the [`core` crate](../core/). When we’re using the standard -library, Rust automatically brings `std` into scope, allowing you to use -its features without an explicit import. By the same token, when using +available via the [`core` crate](../core/index.html). When we’re using the +standard library, Rust automatically brings `std` into scope, allowing you to +use its features without an explicit import. By the same token, when using `#![no_std]`, Rust will bring `core` into scope for you, as well as [its -prelude](../core/prelude/v1/). This means that a lot of code will Just Work: +prelude](../core/prelude/v1/index.html). This means that a lot of code will Just +Work: ```rust #![no_std] diff --git a/src/doc/book/variable-bindings.md b/src/doc/book/variable-bindings.md index 1c8c03cf67..b6751f57a9 100644 --- a/src/doc/book/variable-bindings.md +++ b/src/doc/book/variable-bindings.md @@ -37,8 +37,8 @@ of our minds as we go forward. Rust is a statically typed language, which means that we specify our types up front, and they’re checked at compile time. So why does our first example compile? Well, Rust has this thing called ‘type inference’. If it can figure -out what the type of something is, Rust doesn’t require you to actually type it -out. +out what the type of something is, Rust doesn’t require you to explicitly type +it out. We can add the type if we want to, though. Types come after a colon (`:`): @@ -159,8 +159,9 @@ error: aborting due to previous error Could not compile `hello_world`. ``` -Rust will not let us use a value that has not been initialized. Next, let’s -talk about this stuff we've added to `println!`. +Rust will not let us use a value that has not been initialized. + +Let take a minute to talk about this stuff we've added to `println!`. If you include two curly braces (`{}`, some call them moustaches...) in your string to print, Rust will interpret this as a request to interpolate some sort @@ -222,8 +223,8 @@ To learn more, run the command again with --verbose. ``` Additionally, variable bindings can be shadowed. This means that a later -variable binding with the same name as another binding, that's currently in -scope, will override the previous binding. +variable binding with the same name as another binding that is currently in +scope will override the previous binding. ```rust let x: i32 = 8; @@ -240,7 +241,10 @@ println!("{}", x); // Prints "42" Shadowing and mutable bindings may appear as two sides of the same coin, but they are two distinct concepts that can't always be used interchangeably. For one, shadowing enables us to rebind a name to a value of a different type. It -is also possible to change the mutability of a binding. +is also possible to change the mutability of a binding. Note that shadowing a +name does not alter or destroy the value it was bound to, and the value will +continue to exist until it goes out of scope, even if it is no longer accessible +by any means. ```rust let mut x: i32 = 1; diff --git a/src/doc/book/vectors.md b/src/doc/book/vectors.md index 1c44af2f21..cb6781cdf2 100644 --- a/src/doc/book/vectors.md +++ b/src/doc/book/vectors.md @@ -79,7 +79,7 @@ println!("Item 7 is {}", v[7]); then the current thread will [panic] with a message like this: ```text -thread '
' panicked at 'index out of bounds: the len is 3 but the index is 7' +thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 7' ``` If you want to handle out-of-bounds errors without panicking, you can use @@ -152,5 +152,5 @@ API documentation][vec]. [box]: ../std/boxed/index.html [generic]: generics.html [panic]: concurrency.html#panics -[get]: http://doc.rust-lang.org/std/vec/struct.Vec.html#method.get -[get_mut]: http://doc.rust-lang.org/std/vec/struct.Vec.html#method.get_mut +[get]: ../std/vec/struct.Vec.html#method.get +[get_mut]: ../std/vec/struct.Vec.html#method.get_mut diff --git a/src/doc/footer.inc b/src/doc/footer.inc index 952846dd5e..7513e524e7 100644 --- a/src/doc/footer.inc +++ b/src/doc/footer.inc @@ -1,5 +1,5 @@