From 810390e339a5425391477d5d41c78d7cab2424ac Mon Sep 17 00:00:00 2001 From: robert Date: Fri, 26 Jan 2024 11:27:33 +0000 Subject: [PATCH] import llvm compiler-rt 16.0.6 --- gnu/llvm/compiler-rt/CMakeLists.txt | 295 ++- gnu/llvm/compiler-rt/CODE_OWNERS.TXT | 40 +- .../cmake/Modules/AddCompilerRT.cmake | 134 +- .../cmake/Modules/AllSupportedArchDefs.cmake | 88 + .../cmake/Modules/BuiltinTests.cmake | 4 +- .../cmake/Modules/CheckSectionExists.cmake | 91 + .../cmake/Modules/CompilerRTAIXUtils.cmake | 38 +- .../cmake/Modules/CompilerRTCompile.cmake | 3 +- .../cmake/Modules/CompilerRTDarwinUtils.cmake | 32 +- .../CompilerRTMockLLVMCMakeConfig.cmake | 32 +- .../cmake/Modules/CompilerRTUtils.cmake | 258 +- .../cmake/Modules/SanitizerUtils.cmake | 20 - .../compiler-rt/cmake/base-config-ix.cmake | 98 +- .../compiler-rt/cmake/builtin-config-ix.cmake | 38 +- gnu/llvm/compiler-rt/cmake/config-ix.cmake | 304 ++- .../compiler-rt/cmake/crt-config-ix.cmake | 51 + gnu/llvm/compiler-rt/docs/TestingGuide.rst | 21 +- gnu/llvm/compiler-rt/include/CMakeLists.txt | 20 + gnu/llvm/compiler-rt/include/orc_rt/c_api.h | 205 ++ .../include/profile/InstrProfData.inc | 24 +- .../include/profile/MIBEntryDef.inc | 53 + .../include/profile/MemProfData.inc | 202 ++ .../include/sanitizer/asan_interface.h | 2 +- .../include/sanitizer/common_interface_defs.h | 84 +- .../include/sanitizer/dfsan_interface.h | 51 +- .../include/sanitizer/linux_syscall_hooks.h | 2120 +++++++++-------- .../include/sanitizer/msan_interface.h | 2 + .../include/sanitizer/tsan_interface.h | 3 + gnu/llvm/compiler-rt/lib/CMakeLists.txt | 7 +- gnu/llvm/compiler-rt/lib/asan/CMakeLists.txt | 48 +- .../compiler-rt/lib/asan/asan_activation.cpp | 2 +- .../compiler-rt/lib/asan/asan_allocator.cpp | 123 +- .../compiler-rt/lib/asan/asan_allocator.h | 8 - .../compiler-rt/lib/asan/asan_debugging.cpp | 9 +- .../lib/asan/asan_descriptions.cpp | 21 +- gnu/llvm/compiler-rt/lib/asan/asan_errors.cpp | 78 +- gnu/llvm/compiler-rt/lib/asan/asan_errors.h | 73 +- .../compiler-rt/lib/asan/asan_fake_stack.cpp | 22 +- gnu/llvm/compiler-rt/lib/asan/asan_flags.cpp | 8 +- gnu/llvm/compiler-rt/lib/asan/asan_flags.inc | 11 +- .../compiler-rt/lib/asan/asan_fuchsia.cpp | 67 +- .../compiler-rt/lib/asan/asan_globals.cpp | 55 +- .../lib/asan/asan_interceptors.cpp | 129 +- .../compiler-rt/lib/asan/asan_interceptors.h | 47 +- .../asan/asan_interceptors_memintrinsics.h | 144 +- .../lib/asan/asan_interceptors_vfork.S | 1 + .../compiler-rt/lib/asan/asan_interface.inc | 8 + .../lib/asan/asan_interface_internal.h | 19 +- gnu/llvm/compiler-rt/lib/asan/asan_internal.h | 40 +- gnu/llvm/compiler-rt/lib/asan/asan_linux.cpp | 196 +- gnu/llvm/compiler-rt/lib/asan/asan_mac.cpp | 10 +- .../lib/asan/asan_malloc_linux.cpp | 115 +- .../compiler-rt/lib/asan/asan_malloc_mac.cpp | 2 +- gnu/llvm/compiler-rt/lib/asan/asan_mapping.h | 217 +- .../lib/asan/asan_mapping_sparc64.h | 28 +- .../compiler-rt/lib/asan/asan_new_delete.cpp | 12 +- .../compiler-rt/lib/asan/asan_poisoning.cpp | 350 ++- .../compiler-rt/lib/asan/asan_poisoning.h | 11 +- gnu/llvm/compiler-rt/lib/asan/asan_posix.cpp | 47 +- .../lib/asan/asan_premap_shadow.cpp | 2 +- gnu/llvm/compiler-rt/lib/asan/asan_report.cpp | 47 +- gnu/llvm/compiler-rt/lib/asan/asan_report.h | 4 + gnu/llvm/compiler-rt/lib/asan/asan_rtl.cpp | 112 +- .../compiler-rt/lib/asan/asan_rtl_static.cpp | 36 + .../compiler-rt/lib/asan/asan_rtl_x86_64.S | 146 ++ .../lib/asan/asan_shadow_setup.cpp | 4 +- gnu/llvm/compiler-rt/lib/asan/asan_stats.cpp | 14 +- gnu/llvm/compiler-rt/lib/asan/asan_thread.cpp | 107 +- gnu/llvm/compiler-rt/lib/asan/asan_win.cpp | 44 +- .../lib/asan/asan_win_dll_thunk.cpp | 11 + .../lib/asan/scripts/asan_device_setup | 2 +- .../lib/asan/scripts/asan_symbolize.py | 2 +- .../compiler-rt/lib/asan/tests/CMakeLists.txt | 39 +- .../lib/asan/tests/asan_interface_test.cpp | 7 +- .../tests/asan_internal_interface_test.cpp | 21 + .../lib/asan/tests/asan_mem_test.cpp | 20 +- .../lib/asan/tests/asan_noinst_test.cpp | 111 +- .../lib/asan/tests/asan_oob_test.cpp | 6 +- .../lib/asan/tests/asan_str_test.cpp | 4 +- .../compiler-rt/lib/asan/tests/asan_test.cpp | 44 +- .../lib/asan/tests/asan_test_main.cpp | 17 +- .../compiler-rt/lib/asan/weak_symbols.txt | 7 + .../compiler-rt/lib/builtins/CMakeLists.txt | 136 +- gnu/llvm/compiler-rt/lib/builtins/README.txt | 8 +- .../lib/builtins/aarch64/fp_mode.c | 4 +- .../lib/builtins/apple_versioning.c | 4 +- .../compiler-rt/lib/builtins/arm/fp_mode.c | 4 +- .../compiler-rt/lib/builtins/arm/sync-ops.h | 22 +- .../lib/builtins/arm/truncdfsf2vfp.S | 4 +- gnu/llvm/compiler-rt/lib/builtins/assembly.h | 6 + gnu/llvm/compiler-rt/lib/builtins/atomic.c | 20 + .../compiler-rt/lib/builtins/avr/divmodhi4.S | 57 + .../compiler-rt/lib/builtins/avr/divmodqi4.S | 44 + gnu/llvm/compiler-rt/lib/builtins/avr/exit.S | 18 + .../compiler-rt/lib/builtins/avr/mulhi3.S | 71 + .../compiler-rt/lib/builtins/avr/mulqi3.S | 53 + .../compiler-rt/lib/builtins/avr/udivmodhi4.S | 49 + .../compiler-rt/lib/builtins/avr/udivmodqi4.S | 39 + gnu/llvm/compiler-rt/lib/builtins/cpu_model.c | 602 ++++- gnu/llvm/compiler-rt/lib/builtins/eprintf.c | 2 + gnu/llvm/compiler-rt/lib/builtins/fixdfdi.c | 4 + gnu/llvm/compiler-rt/lib/builtins/fixsfdi.c | 4 + .../compiler-rt/lib/builtins/fixunsdfdi.c | 4 + .../compiler-rt/lib/builtins/fixunssfdi.c | 4 + .../compiler-rt/lib/builtins/fixunsxfdi.c | 2 +- .../compiler-rt/lib/builtins/fixunsxfsi.c | 2 +- gnu/llvm/compiler-rt/lib/builtins/fixxfdi.c | 2 +- gnu/llvm/compiler-rt/lib/builtins/floatdidf.c | 4 + gnu/llvm/compiler-rt/lib/builtins/floatdisf.c | 4 + gnu/llvm/compiler-rt/lib/builtins/floatsisf.c | 4 +- gnu/llvm/compiler-rt/lib/builtins/floatsitf.c | 8 +- .../compiler-rt/lib/builtins/floatundidf.c | 4 + .../compiler-rt/lib/builtins/floatundisf.c | 4 + .../compiler-rt/lib/builtins/floatunsisf.c | 4 +- .../compiler-rt/lib/builtins/floatunsitf.c | 4 +- .../lib/builtins/fp_compare_impl.inc | 3 + gnu/llvm/compiler-rt/lib/builtins/fp_extend.h | 4 +- gnu/llvm/compiler-rt/lib/builtins/fp_mode.c | 4 +- gnu/llvm/compiler-rt/lib/builtins/fp_mode.h | 4 +- gnu/llvm/compiler-rt/lib/builtins/fp_trunc.h | 6 + .../lib/builtins/gcc_personality_v0.c | 2 +- .../compiler-rt/lib/builtins/i386/fp_mode.c | 4 +- .../compiler-rt/lib/builtins/int_endianness.h | 2 +- gnu/llvm/compiler-rt/lib/builtins/int_types.h | 2 +- .../lib/builtins/loongarch/fp_mode.c | 59 + .../lib/builtins/macho_embedded/common.txt | 1 + .../lib/builtins/os_version_check.c | 4 +- .../compiler-rt/lib/builtins/riscv/fp_mode.c | 42 + .../compiler-rt/lib/builtins/riscv/restore.S | 10 +- .../compiler-rt/lib/builtins/riscv/save.S | 2 + .../lib/builtins/trampoline_setup.c | 4 +- .../compiler-rt/lib/builtins/truncdfbf2.c | 13 + .../compiler-rt/lib/builtins/truncsfbf2.c | 13 + .../compiler-rt/lib/builtins/udivmoddi4.c | 6 +- gnu/llvm/compiler-rt/lib/cfi/CMakeLists.txt | 3 + gnu/llvm/compiler-rt/lib/cfi/cfi.cpp | 16 +- gnu/llvm/compiler-rt/lib/crt/CMakeLists.txt | 156 +- gnu/llvm/compiler-rt/lib/crt/crtbegin.c | 4 +- gnu/llvm/compiler-rt/lib/dfsan/CMakeLists.txt | 3 + gnu/llvm/compiler-rt/lib/dfsan/dfsan.cpp | 402 +++- gnu/llvm/compiler-rt/lib/dfsan/dfsan.h | 12 +- .../compiler-rt/lib/dfsan/dfsan_allocator.cpp | 14 +- .../compiler-rt/lib/dfsan/dfsan_custom.cpp | 279 +-- .../lib/dfsan/dfsan_interceptors.cpp | 65 +- .../compiler-rt/lib/dfsan/dfsan_platform.h | 31 +- .../compiler-rt/lib/dfsan/dfsan_thread.cpp | 30 +- gnu/llvm/compiler-rt/lib/dfsan/dfsan_thread.h | 9 +- .../compiler-rt/lib/dfsan/done_abilist.txt | 19 +- .../lib/dfsan/libc_ubuntu1404_abilist.txt | 1 + .../lib/dfsan/scripts/build-libc-list.py | 83 +- .../compiler-rt/lib/fuzzer/CMakeLists.txt | 20 +- .../lib/fuzzer/FuzzerBuiltinsMsvc.h | 3 +- .../compiler-rt/lib/fuzzer/FuzzerCommand.h | 12 +- .../compiler-rt/lib/fuzzer/FuzzerCorpus.h | 25 +- .../lib/fuzzer/FuzzerDataFlowTrace.cpp | 32 +- .../lib/fuzzer/FuzzerDataFlowTrace.h | 16 +- gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDefs.h | 24 +- .../compiler-rt/lib/fuzzer/FuzzerDictionary.h | 11 +- .../compiler-rt/lib/fuzzer/FuzzerDriver.cpp | 74 +- .../lib/fuzzer/FuzzerExtraCounters.cpp | 8 - .../lib/fuzzer/FuzzerExtraCountersDarwin.cpp | 22 + .../lib/fuzzer/FuzzerExtraCountersWindows.cpp | 80 + .../compiler-rt/lib/fuzzer/FuzzerFlags.def | 9 + .../compiler-rt/lib/fuzzer/FuzzerFork.cpp | 126 +- gnu/llvm/compiler-rt/lib/fuzzer/FuzzerFork.h | 4 +- gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIO.cpp | 18 +- gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIO.h | 12 +- .../compiler-rt/lib/fuzzer/FuzzerIOPosix.cpp | 3 +- .../lib/fuzzer/FuzzerIOWindows.cpp | 8 +- .../compiler-rt/lib/fuzzer/FuzzerInternal.h | 17 +- .../compiler-rt/lib/fuzzer/FuzzerLoop.cpp | 43 +- .../compiler-rt/lib/fuzzer/FuzzerMerge.cpp | 211 +- gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMerge.h | 38 +- .../compiler-rt/lib/fuzzer/FuzzerMutate.cpp | 6 +- .../compiler-rt/lib/fuzzer/FuzzerMutate.h | 18 +- .../compiler-rt/lib/fuzzer/FuzzerOptions.h | 1 + .../compiler-rt/lib/fuzzer/FuzzerTracePC.cpp | 19 +- .../compiler-rt/lib/fuzzer/FuzzerTracePC.h | 2 +- .../compiler-rt/lib/fuzzer/FuzzerUtil.cpp | 4 +- gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtil.h | 4 +- .../lib/fuzzer/FuzzerUtilFuchsia.cpp | 156 +- .../lib/fuzzer/FuzzerUtilLinux.cpp | 4 + .../lib/fuzzer/FuzzerUtilWindows.cpp | 2 +- .../lib/fuzzer/tests/CMakeLists.txt | 7 +- .../lib/fuzzer/tests/FuzzerUnittest.cpp | 257 +- .../compiler-rt/lib/gwp_asan/CMakeLists.txt | 3 +- gnu/llvm/compiler-rt/lib/gwp_asan/common.cpp | 4 + gnu/llvm/compiler-rt/lib/gwp_asan/common.h | 68 +- .../lib/gwp_asan/crash_handler.cpp | 26 +- .../compiler-rt/lib/gwp_asan/crash_handler.h | 16 +- .../lib/gwp_asan/guarded_pool_allocator.cpp | 151 +- .../lib/gwp_asan/guarded_pool_allocator.h | 13 +- .../optional/backtrace_sanitizer_common.cpp | 4 +- .../lib/gwp_asan/optional/segv_handler.h | 3 +- .../optional/segv_handler_fuchsia.cpp | 3 +- .../gwp_asan/optional/segv_handler_posix.cpp | 84 +- gnu/llvm/compiler-rt/lib/gwp_asan/options.inc | 10 + .../guarded_pool_allocator_posix.cpp | 4 + .../lib/gwp_asan/scripts/symbolize.sh | 2 +- .../lib/gwp_asan/tests/CMakeLists.txt | 12 +- .../lib/gwp_asan/tests/alignment.cpp | 82 +- .../lib/gwp_asan/tests/backtrace.cpp | 83 +- .../lib/gwp_asan/tests/crash_handler_api.cpp | 21 +- .../lib/gwp_asan/tests/harness.cpp | 18 + .../compiler-rt/lib/gwp_asan/tests/harness.h | 41 +- .../lib/gwp_asan/tests/iterate.cpp | 1 + .../lib/gwp_asan/tests/recoverable.cpp | 210 ++ .../compiler-rt/lib/hwasan/CMakeLists.txt | 33 +- gnu/llvm/compiler-rt/lib/hwasan/hwasan.cpp | 80 +- gnu/llvm/compiler-rt/lib/hwasan/hwasan.h | 53 +- .../hwasan/hwasan_allocation_functions.cpp | 81 +- .../lib/hwasan/hwasan_allocator.cpp | 281 ++- .../compiler-rt/lib/hwasan/hwasan_allocator.h | 34 +- .../compiler-rt/lib/hwasan/hwasan_checks.h | 19 +- .../lib/hwasan/hwasan_exceptions.cpp | 6 +- .../compiler-rt/lib/hwasan/hwasan_flags.inc | 2 +- .../compiler-rt/lib/hwasan/hwasan_fuchsia.cpp | 36 +- .../lib/hwasan/hwasan_interceptors.cpp | 128 +- .../lib/hwasan/hwasan_interface_internal.h | 52 +- .../compiler-rt/lib/hwasan/hwasan_linux.cpp | 335 ++- .../lib/hwasan/hwasan_memintrinsics.cpp | 2 +- .../lib/hwasan/hwasan_new_delete.cpp | 63 +- .../lib/hwasan/hwasan_poisoning.cpp | 8 + .../compiler-rt/lib/hwasan/hwasan_preinit.cpp | 23 + .../compiler-rt/lib/hwasan/hwasan_report.cpp | 156 +- .../lib/hwasan/hwasan_setjmp_aarch64.S | 101 + .../lib/hwasan/hwasan_setjmp_riscv64.S | 97 + .../lib/hwasan/hwasan_setjmp_x86_64.S | 82 + .../lib/hwasan/hwasan_tag_mismatch_riscv64.S | 132 + .../compiler-rt/lib/hwasan/hwasan_thread.cpp | 85 +- .../compiler-rt/lib/hwasan/hwasan_thread.h | 21 +- .../lib/hwasan/hwasan_thread_list.h | 43 +- .../lib/hwasan/hwasan_type_test.cpp | 2 +- .../lib/hwasan/scripts/hwasan_symbolize | 534 +++-- .../lib/interception/CMakeLists.txt | 5 + .../lib/interception/interception_mac.cpp | 4 +- .../lib/interception/interception_mac.h | 4 +- .../interception/interception_type_test.cpp | 6 +- .../lib/interception/interception_win.cpp | 55 +- .../lib/interception/tests/CMakeLists.txt | 7 +- .../tests/interception_win_test.cpp | 81 +- gnu/llvm/compiler-rt/lib/lsan/CMakeLists.txt | 5 +- gnu/llvm/compiler-rt/lib/lsan/lsan.cpp | 9 +- gnu/llvm/compiler-rt/lib/lsan/lsan.h | 26 +- .../compiler-rt/lib/lsan/lsan_allocator.cpp | 29 +- .../compiler-rt/lib/lsan/lsan_allocator.h | 10 +- gnu/llvm/compiler-rt/lib/lsan/lsan_common.cpp | 690 +++--- gnu/llvm/compiler-rt/lib/lsan/lsan_common.h | 206 +- .../lib/lsan/lsan_common_fuchsia.cpp | 28 +- .../lib/lsan/lsan_common_linux.cpp | 5 +- .../compiler-rt/lib/lsan/lsan_common_mac.cpp | 91 +- .../compiler-rt/lib/lsan/lsan_fuchsia.cpp | 16 +- .../lib/lsan/lsan_interceptors.cpp | 76 +- gnu/llvm/compiler-rt/lib/lsan/lsan_mac.cpp | 6 +- .../compiler-rt/lib/lsan/lsan_malloc_mac.cpp | 4 +- gnu/llvm/compiler-rt/lib/lsan/lsan_posix.cpp | 10 +- gnu/llvm/compiler-rt/lib/lsan/lsan_thread.cpp | 44 +- gnu/llvm/compiler-rt/lib/lsan/lsan_thread.h | 7 +- .../compiler-rt/lib/memprof/CMakeLists.txt | 19 +- .../lib/memprof/memprof_allocator.cpp | 399 +--- .../lib/memprof/memprof_allocator.h | 1 - .../compiler-rt/lib/memprof/memprof_flags.inc | 14 +- .../lib/memprof/memprof_interceptors.cpp | 16 +- .../lib/memprof/memprof_interceptors.h | 4 +- .../lib/memprof/memprof_internal.h | 17 - .../compiler-rt/lib/memprof/memprof_linux.cpp | 6 - .../lib/memprof/memprof_malloc_linux.cpp | 103 +- .../lib/memprof/memprof_mibmap.cpp | 37 + .../compiler-rt/lib/memprof/memprof_mibmap.h | 27 + .../lib/memprof/memprof_rawprofile.cpp | 246 ++ .../lib/memprof/memprof_rawprofile.h | 14 + .../compiler-rt/lib/memprof/memprof_rtl.cpp | 32 +- .../compiler-rt/lib/memprof/memprof_stats.cpp | 14 +- .../lib/memprof/memprof_thread.cpp | 11 +- .../lib/memprof/tests/CMakeLists.txt | 71 + .../compiler-rt/lib/memprof/tests/driver.cpp | 14 + .../lib/memprof/tests/rawprofile.cpp | 197 ++ gnu/llvm/compiler-rt/lib/msan/msan.cpp | 112 +- gnu/llvm/compiler-rt/lib/msan/msan.h | 174 +- .../compiler-rt/lib/msan/msan_allocator.cpp | 30 +- .../lib/msan/msan_chained_origin_depot.cpp | 2 +- .../lib/msan/msan_chained_origin_depot.h | 2 +- gnu/llvm/compiler-rt/lib/msan/msan_flags.inc | 2 +- .../lib/msan/msan_interceptors.cpp | 273 ++- .../lib/msan/msan_interface_internal.h | 11 +- gnu/llvm/compiler-rt/lib/msan/msan_linux.cpp | 12 +- .../compiler-rt/lib/msan/msan_poisoning.cpp | 4 + gnu/llvm/compiler-rt/lib/msan/msan_report.cpp | 53 +- gnu/llvm/compiler-rt/lib/msan/msan_thread.cpp | 2 - gnu/llvm/compiler-rt/lib/msan/msan_thread.h | 3 +- .../compiler-rt/lib/msan/tests/CMakeLists.txt | 6 +- .../compiler-rt/lib/msan/tests/msan_test.cpp | 57 +- gnu/llvm/compiler-rt/lib/orc/CMakeLists.txt | 133 +- gnu/llvm/compiler-rt/lib/orc/adt.h | 54 +- .../compiler-rt/lib/orc/coff_platform.cpp | 769 ++++++ gnu/llvm/compiler-rt/lib/orc/coff_platform.h | 39 + .../lib/orc/coff_platform.per_jd.cpp | 31 + gnu/llvm/compiler-rt/lib/orc/common.h | 6 +- gnu/llvm/compiler-rt/lib/orc/compiler.h | 11 +- gnu/llvm/compiler-rt/lib/orc/debug.cpp | 83 + gnu/llvm/compiler-rt/lib/orc/debug.h | 56 + .../compiler-rt/lib/orc/dlfcn_wrapper.cpp | 52 + .../compiler-rt/lib/orc/elfnix_platform.cpp | 605 +++++ .../compiler-rt/lib/orc/elfnix_platform.h | 131 + .../compiler-rt/lib/orc/elfnix_tls.aarch64.S | 94 + .../compiler-rt/lib/orc/elfnix_tls.x86-64.S | 64 + gnu/llvm/compiler-rt/lib/orc/error.h | 4 +- .../compiler-rt/lib/orc/executor_address.h | 225 +- gnu/llvm/compiler-rt/lib/orc/interval_map.h | 168 ++ gnu/llvm/compiler-rt/lib/orc/interval_set.h | 87 + .../compiler-rt/lib/orc/macho_platform.cpp | 1369 ++++++++--- gnu/llvm/compiler-rt/lib/orc/macho_platform.h | 91 - .../compiler-rt/lib/orc/macho_tlv.arm64.S | 92 + .../compiler-rt/lib/orc/macho_tlv.x86-64.S | 5 + .../lib/orc/run_program_wrapper.cpp | 2 +- .../lib/orc/simple_packed_serialization.h | 77 +- gnu/llvm/compiler-rt/lib/orc/stl_extras.h | 31 +- gnu/llvm/compiler-rt/lib/orc/string_pool.h | 172 ++ .../compiler-rt/lib/orc/tests/CMakeLists.txt | 111 + .../lib/orc/tests/tools/CMakeLists.txt | 1 + .../lib/orc/tests/tools/orc-rt-executor.cpp | 49 + .../lib/orc/tests/unit/CMakeLists.txt | 18 + .../lib/orc/tests/unit/adt_test.cpp | 50 + .../lib/orc/tests/unit/c_api_test.cpp | 200 ++ .../lib/orc/tests/unit/endian_test.cpp | 174 ++ .../lib/orc/tests/unit/error_test.cpp | 295 +++ .../orc/tests/unit/executor_address_test.cpp | 115 + .../orc/tests/unit/extensible_rtti_test.cpp | 54 + .../lib/orc/tests/unit/interval_map_test.cpp | 204 ++ .../lib/orc/tests/unit/interval_set_test.cpp | 121 + .../lib/orc/tests/unit/orc_unit_test_main.cpp | 18 + .../unit/simple_packed_serialization_test.cpp | 197 ++ .../lib/orc/tests/unit/string_pool_test.cpp | 66 + .../unit/wrapper_function_utils_test.cpp | 184 ++ .../lib/orc/wrapper_function_utils.h | 228 +- .../compiler-rt/lib/profile/CMakeLists.txt | 7 +- .../compiler-rt/lib/profile/GCDAProfiling.c | 25 +- .../compiler-rt/lib/profile/InstrProfiling.c | 20 +- .../compiler-rt/lib/profile/InstrProfiling.h | 51 +- .../lib/profile/InstrProfilingBuffer.c | 58 +- .../lib/profile/InstrProfilingFile.c | 497 ++-- .../lib/profile/InstrProfilingInternal.c | 2 +- .../lib/profile/InstrProfilingInternal.h | 15 +- .../lib/profile/InstrProfilingMerge.c | 94 +- .../lib/profile/InstrProfilingNameVar.c | 2 +- .../profile/InstrProfilingPlatformDarwin.c | 9 +- .../profile/InstrProfilingPlatformFuchsia.c | 19 +- .../lib/profile/InstrProfilingPlatformLinux.c | 115 +- .../lib/profile/InstrProfilingPlatformOther.c | 26 +- .../profile/InstrProfilingPlatformWindows.c | 8 +- .../lib/profile/InstrProfilingRuntime.cpp | 22 +- .../lib/profile/InstrProfilingUtil.c | 26 +- .../lib/profile/InstrProfilingValue.c | 6 +- .../lib/profile/InstrProfilingVersionVar.c | 3 +- .../lib/profile/InstrProfilingWriter.c | 59 +- .../lib/safestack/safestack_platform.h | 2 +- .../lib/sanitizer_common/CMakeLists.txt | 39 +- .../lib/sanitizer_common/sancov_flags.inc | 2 +- .../sanitizer_common/sanitizer_addrhashmap.h | 46 +- .../sanitizer_common/sanitizer_allocator.cpp | 83 +- .../sanitizer_common/sanitizer_allocator.h | 11 +- .../sanitizer_allocator_combined.h | 12 +- .../sanitizer_allocator_dlsym.h | 79 + .../sanitizer_allocator_internal.h | 2 + .../sanitizer_allocator_primary32.h | 21 +- .../sanitizer_allocator_primary64.h | 25 +- .../sanitizer_allocator_report.cpp | 3 +- .../sanitizer_allocator_secondary.h | 14 +- .../sanitizer_allocator_size_class_map.h | 8 +- .../lib/sanitizer_common/sanitizer_asm.h | 11 +- .../sanitizer_common/sanitizer_atomic_clang.h | 17 +- .../sanitizer_atomic_clang_mips.h | 2 +- .../sanitizer_chained_origin_depot.cpp | 84 +- .../sanitizer_chained_origin_depot.h | 46 +- .../lib/sanitizer_common/sanitizer_common.cpp | 58 +- .../lib/sanitizer_common/sanitizer_common.h | 124 +- .../sanitizer_common_interceptors.inc | 1152 +++++---- .../sanitizer_common_interceptors_format.inc | 10 +- .../sanitizer_common_interceptors_ioctl.inc | 10 +- ...izer_common_interceptors_netbsd_compat.inc | 4 +- ...tizer_common_interceptors_vfork_i386.inc.S | 1 + ...ommon_interceptors_vfork_loongarch64.inc.S | 57 + ...zer_common_interceptors_vfork_x86_64.inc.S | 1 + .../sanitizer_common_interface.inc | 4 + .../sanitizer_common_interface_posix.inc | 2 + .../sanitizer_common_libcdep.cpp | 97 +- .../sanitizer_common_nolibc.cpp | 3 +- .../sanitizer_common_syscalls.inc | 1578 +++++++----- .../sanitizer_coverage_fuchsia.cpp | 9 +- .../sanitizer_coverage_interface.inc | 10 + .../sanitizer_coverage_libcdep_new.cpp | 95 +- .../sanitizer_deadlock_detector.h | 2 +- .../sanitizer_common/sanitizer_dense_map.h | 705 ++++++ .../sanitizer_dense_map_info.h | 282 +++ .../lib/sanitizer_common/sanitizer_errno.h | 2 +- .../sanitizer_common/sanitizer_errno_codes.h | 1 + .../lib/sanitizer_common/sanitizer_file.cpp | 20 + .../lib/sanitizer_common/sanitizer_file.h | 4 +- .../sanitizer_common/sanitizer_flag_parser.h | 2 +- .../lib/sanitizer_common/sanitizer_flags.inc | 20 +- .../lib/sanitizer_common/sanitizer_flat_map.h | 173 ++ .../sanitizer_common/sanitizer_fuchsia.cpp | 110 +- .../lib/sanitizer_common/sanitizer_hash.h | 24 + .../sanitizer_interceptors_ioctl_netbsd.inc | 2 +- .../sanitizer_interface_internal.h | 211 +- .../sanitizer_internal_defs.h | 73 +- .../lib/sanitizer_common/sanitizer_leb128.h | 87 + .../lib/sanitizer_common/sanitizer_libc.cpp | 12 + .../lib/sanitizer_common/sanitizer_libc.h | 5 +- .../sanitizer_common/sanitizer_libignore.cpp | 12 +- .../sanitizer_common/sanitizer_libignore.h | 2 +- .../sanitizer_linux_libcdep.cpp | 137 +- .../sanitizer_common/sanitizer_linux_s390.cpp | 14 +- .../sanitizer_local_address_space_view.h | 2 +- .../lib/sanitizer_common/sanitizer_lzw.h | 159 ++ .../lib/sanitizer_common/sanitizer_mac.cpp | 309 +-- .../lib/sanitizer_common/sanitizer_mac.h | 21 +- .../sanitizer_mac_libcdep.cpp | 4 +- .../sanitizer_common/sanitizer_malloc_mac.inc | 22 +- .../lib/sanitizer_common/sanitizer_mutex.cpp | 4 +- .../lib/sanitizer_common/sanitizer_mutex.h | 281 +-- .../sanitizer_platform_interceptors.h | 76 +- .../sanitizer_platform_limits_freebsd.cpp | 31 +- .../sanitizer_platform_limits_freebsd.h | 219 +- .../sanitizer_platform_limits_linux.cpp | 63 +- .../sanitizer_platform_limits_netbsd.cpp | 3 +- .../sanitizer_platform_limits_netbsd.h | 3 +- .../sanitizer_platform_limits_posix.cpp | 141 +- .../sanitizer_platform_limits_posix.h | 132 +- .../sanitizer_platform_limits_solaris.cpp | 3 +- .../sanitizer_platform_limits_solaris.h | 3 +- .../lib/sanitizer_common/sanitizer_posix.cpp | 18 +- .../lib/sanitizer_common/sanitizer_posix.h | 7 +- .../sanitizer_posix_libcdep.cpp | 6 +- .../lib/sanitizer_common/sanitizer_printf.cpp | 37 +- .../lib/sanitizer_common/sanitizer_procmaps.h | 20 +- .../sanitizer_procmaps_bsd.cpp | 16 + .../sanitizer_procmaps_common.cpp | 28 +- .../sanitizer_procmaps_mac.cpp | 92 +- .../sanitizer_procmaps_solaris.cpp | 50 +- .../sanitizer_common/sanitizer_quarantine.h | 4 +- .../sanitizer_common/sanitizer_ring_buffer.h | 13 +- .../sanitizer_signal_interceptors.inc | 12 +- .../sanitizer_common/sanitizer_solaris.cpp | 22 - .../lib/sanitizer_common/sanitizer_solaris.h | 56 + .../sanitizer_stack_store.cpp | 379 +++ .../sanitizer_common/sanitizer_stack_store.h | 121 + .../sanitizer_common/sanitizer_stackdepot.cpp | 255 +- .../sanitizer_common/sanitizer_stackdepot.h | 39 +- .../sanitizer_stackdepotbase.h | 173 +- .../sanitizer_common/sanitizer_stacktrace.cpp | 16 +- .../sanitizer_common/sanitizer_stacktrace.h | 15 +- .../sanitizer_stacktrace_libcdep.cpp | 15 +- .../sanitizer_stacktrace_printer.cpp | 31 +- .../sanitizer_stacktrace_sparc.cpp | 2 +- .../sanitizer_stoptheworld_linux_libcdep.cpp | 14 +- .../sanitizer_stoptheworld_mac.cpp | 13 +- .../sanitizer_stoptheworld_netbsd_libcdep.cpp | 2 +- .../sanitizer_stoptheworld_win.cpp | 175 ++ .../sanitizer_common/sanitizer_symbolizer.cpp | 20 +- .../sanitizer_common/sanitizer_symbolizer.h | 13 +- .../sanitizer_symbolizer_internal.h | 15 +- .../sanitizer_symbolizer_libcdep.cpp | 91 +- .../sanitizer_symbolizer_mac.cpp | 61 +- .../sanitizer_symbolizer_mac.h | 5 +- .../sanitizer_symbolizer_markup.cpp | 4 +- .../sanitizer_symbolizer_posix_libcdep.cpp | 95 +- .../sanitizer_symbolizer_report.cpp | 14 +- .../sanitizer_symbolizer_win.cpp | 4 +- .../sanitizer_syscall_generic.inc | 5 +- .../sanitizer_syscall_linux_hexagon.inc | 131 + .../sanitizer_syscall_linux_loongarch64.inc | 171 ++ .../sanitizer_syscalls_netbsd.inc | 4 +- .../sanitizer_thread_registry.cpp | 78 +- .../sanitizer_thread_registry.h | 20 +- .../sanitizer_thread_safety.h | 45 +- .../sanitizer_tls_get_addr.cpp | 28 +- .../sanitizer_common/sanitizer_type_traits.h | 79 + .../sanitizer_unwind_linux_libcdep.cpp | 2 +- .../sanitizer_common/sanitizer_unwind_win.cpp | 27 +- .../lib/sanitizer_common/sanitizer_vector.h | 4 +- .../lib/sanitizer_common/sanitizer_win.cpp | 80 +- .../symbolizer/sanitizer_symbolize.cpp | 39 +- .../symbolizer/sanitizer_wrappers.cpp | 11 +- .../symbolizer/scripts/build_symbolizer.sh | 100 +- .../symbolizer/scripts/global_symbols.txt | 23 +- .../lib/sanitizer_common/tests/CMakeLists.txt | 24 +- .../tests/sanitizer_addrhashmap_test.cpp | 62 + .../tests/sanitizer_allocator_test.cpp | 63 - .../tests/sanitizer_bitvector_test.cpp | 2 +- .../sanitizer_chained_origin_depot_test.cpp | 17 +- .../tests/sanitizer_common_test.cpp | 37 +- .../tests/sanitizer_dense_map_test.cpp | 550 +++++ .../tests/sanitizer_flat_map_test.cpp | 113 + .../tests/sanitizer_hash_test.cpp | 48 + .../tests/sanitizer_leb128_test.cpp | 85 + .../tests/sanitizer_libc_test.cpp | 71 +- .../tests/sanitizer_lzw_test.cpp | 89 + .../tests/sanitizer_mac_test.cpp | 4 +- .../tests/sanitizer_mutex_test.cpp | 17 +- .../tests/sanitizer_printf_test.cpp | 31 +- .../tests/sanitizer_procmaps_test.cpp | 72 +- .../tests/sanitizer_stack_store_test.cpp | 200 ++ .../tests/sanitizer_stackdepot_test.cpp | 163 +- .../sanitizer_stacktrace_printer_test.cpp | 22 + .../tests/sanitizer_stacktrace_test.cpp | 4 +- .../tests/sanitizer_stoptheworld_test.cpp | 178 +- .../tests/sanitizer_thread_registry_test.cpp | 4 +- .../tests/sanitizer_type_traits_test.cpp | 53 +- .../lib/sanitizer_common/weak_symbols.txt | 2 + .../lib/scudo/standalone/CMakeLists.txt | 75 +- .../lib/scudo/standalone/allocator_config.h | 16 + .../lib/scudo/standalone/checksum.cpp | 1 + .../lib/scudo/standalone/checksum.h | 9 +- .../compiler-rt/lib/scudo/standalone/chunk.h | 5 +- .../lib/scudo/standalone/combined.h | 139 +- .../lib/scudo/standalone/common.cpp | 4 + .../compiler-rt/lib/scudo/standalone/common.h | 5 +- .../lib/scudo/standalone/crc32_hw.cpp | 5 +- .../lib/scudo/standalone/flags.inc | 12 + .../lib/scudo/standalone/fuchsia.cpp | 24 +- .../lib/scudo/standalone/fuchsia.h | 3 +- .../standalone/fuzz/get_error_info_fuzzer.cpp | 11 +- .../standalone/include/scudo/interface.h | 14 +- .../lib/scudo/standalone/internal_defs.h | 34 +- .../lib/scudo/standalone/linux.cpp | 34 + .../compiler-rt/lib/scudo/standalone/list.h | 12 + .../lib/scudo/standalone/local_cache.h | 74 +- .../compiler-rt/lib/scudo/standalone/memtag.h | 45 +- .../lib/scudo/standalone/platform.h | 2 +- .../lib/scudo/standalone/primary32.h | 333 ++- .../lib/scudo/standalone/primary64.h | 377 ++- .../lib/scudo/standalone/release.cpp | 4 +- .../lib/scudo/standalone/release.h | 323 ++- .../lib/scudo/standalone/report.cpp | 12 + .../compiler-rt/lib/scudo/standalone/report.h | 2 + .../scudo/standalone/rss_limit_checker.cpp | 37 + .../lib/scudo/standalone/rss_limit_checker.h | 63 + .../lib/scudo/standalone/secondary.h | 33 +- .../lib/scudo/standalone/size_class_map.h | 35 +- .../lib/scudo/standalone/string_utils.cpp | 2 - .../lib/scudo/standalone/string_utils.h | 8 +- .../lib/scudo/standalone/tests/CMakeLists.txt | 17 +- .../scudo/standalone/tests/checksum_test.cpp | 10 +- .../scudo/standalone/tests/combined_test.cpp | 114 +- .../scudo/standalone/tests/common_test.cpp | 21 + .../lib/scudo/standalone/tests/list_test.cpp | 4 + .../lib/scudo/standalone/tests/map_test.cpp | 2 +- .../scudo/standalone/tests/memtag_test.cpp | 2 +- .../lib/scudo/standalone/tests/mutex_test.cpp | 2 +- .../scudo/standalone/tests/primary_test.cpp | 86 +- .../scudo/standalone/tests/release_test.cpp | 57 +- .../scudo/standalone/tests/secondary_test.cpp | 3 +- .../standalone/tests/size_class_map_test.cpp | 4 +- .../scudo/standalone/tests/strings_test.cpp | 5 +- .../lib/scudo/standalone/tests/tsd_test.cpp | 4 +- .../standalone/tests/wrappers_c_test.cpp | 26 +- .../standalone/tests/wrappers_cpp_test.cpp | 27 +- .../tools/compute_size_class_config.cpp | 2 +- .../lib/scudo/standalone/tsd_exclusive.h | 4 +- .../compiler-rt/lib/scudo/standalone/vector.h | 22 +- .../lib/scudo/standalone/wrappers_c.cpp | 2 - .../lib/scudo/standalone/wrappers_c.h | 18 + .../lib/scudo/standalone/wrappers_c.inc | 19 +- .../lib/scudo/standalone/wrappers_c_checks.h | 9 +- .../lib/scudo/standalone/wrappers_cpp.cpp | 18 +- gnu/llvm/compiler-rt/lib/stats/CMakeLists.txt | 4 +- gnu/llvm/compiler-rt/lib/tsan/CMakeLists.txt | 253 +- .../compiler-rt/lib/tsan/analyze_libtsan.sh | 2 +- .../compiler-rt/lib/tsan/check_analyze.sh | 14 +- gnu/llvm/compiler-rt/lib/tsan/check_cmake.sh | 2 +- .../compiler-rt/lib/tsan/dd/CMakeLists.txt | 5 +- .../lib/tsan/dd/dd_interceptors.cpp | 3 +- gnu/llvm/compiler-rt/lib/tsan/dd/dd_rtl.cpp | 6 +- gnu/llvm/compiler-rt/lib/tsan/dd/dd_rtl.h | 6 +- gnu/llvm/compiler-rt/lib/tsan/go/build.bat | 12 +- gnu/llvm/compiler-rt/lib/tsan/go/buildgo.sh | 15 +- gnu/llvm/compiler-rt/lib/tsan/go/test.c | 2 +- gnu/llvm/compiler-rt/lib/tsan/go/tsan_go.cpp | 41 +- .../compiler-rt/lib/tsan/rtl/CMakeLists.txt | 291 +++ .../compiler-rt/lib/tsan/rtl/tsan.syms.extra | 3 + .../lib/tsan/rtl/tsan_debugging.cpp | 12 +- gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_defs.h | 100 +- .../lib/tsan/rtl/tsan_dense_alloc.h | 134 +- .../lib/tsan/rtl/tsan_dispatch_defs.h | 2 +- .../lib/tsan/rtl/tsan_external.cpp | 19 +- gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_fd.cpp | 113 +- gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_fd.h | 3 +- .../compiler-rt/lib/tsan/rtl/tsan_flags.cpp | 9 +- .../compiler-rt/lib/tsan/rtl/tsan_flags.inc | 25 +- .../lib/tsan/rtl/tsan_ignoreset.cpp | 12 +- .../compiler-rt/lib/tsan/rtl/tsan_ignoreset.h | 13 +- .../compiler-rt/lib/tsan/rtl/tsan_ilist.h | 189 ++ .../lib/tsan/rtl/tsan_interceptors.h | 78 +- .../rtl/tsan_interceptors_libdispatch.cpp | 4 +- .../lib/tsan/rtl/tsan_interceptors_mac.cpp | 10 +- .../lib/tsan/rtl/tsan_interceptors_posix.cpp | 950 +++++--- .../lib/tsan/rtl/tsan_interface.cpp | 99 +- .../compiler-rt/lib/tsan/rtl/tsan_interface.h | 17 +- .../lib/tsan/rtl/tsan_interface.inc | 190 ++ .../lib/tsan/rtl/tsan_interface_ann.cpp | 169 +- .../lib/tsan/rtl/tsan_interface_atomic.cpp | 336 ++- .../lib/tsan/rtl/tsan_interface_java.cpp | 294 ++- .../lib/tsan/rtl/tsan_malloc_mac.cpp | 2 +- .../compiler-rt/lib/tsan/rtl/tsan_mman.cpp | 92 +- gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_mman.h | 53 +- .../lib/tsan/rtl/tsan_mutexset.cpp | 48 +- .../compiler-rt/lib/tsan/rtl/tsan_mutexset.h | 60 +- .../compiler-rt/lib/tsan/rtl/tsan_platform.h | 1405 +++++------ .../lib/tsan/rtl/tsan_platform_linux.cpp | 150 +- .../lib/tsan/rtl/tsan_platform_mac.cpp | 279 +-- .../lib/tsan/rtl/tsan_platform_posix.cpp | 51 +- .../lib/tsan/rtl/tsan_platform_windows.cpp | 6 +- .../compiler-rt/lib/tsan/rtl/tsan_report.cpp | 101 +- .../compiler-rt/lib/tsan/rtl/tsan_report.h | 43 +- .../compiler-rt/lib/tsan/rtl/tsan_rtl.cpp | 1350 +++++------ gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_rtl.h | 805 +++---- .../lib/tsan/rtl/tsan_rtl_access.cpp | 744 ++++++ .../compiler-rt/lib/tsan/rtl/tsan_rtl_amd64.S | 164 +- .../lib/tsan/rtl/tsan_rtl_loongarch64.S | 196 ++ .../lib/tsan/rtl/tsan_rtl_mutex.cpp | 707 +++--- .../lib/tsan/rtl/tsan_rtl_proc.cpp | 1 - .../lib/tsan/rtl/tsan_rtl_report.cpp | 668 +++--- .../compiler-rt/lib/tsan/rtl/tsan_rtl_s390x.S | 2 + .../lib/tsan/rtl/tsan_rtl_thread.cpp | 453 ++-- .../compiler-rt/lib/tsan/rtl/tsan_shadow.h | 193 ++ .../lib/tsan/rtl/tsan_stack_trace.cpp | 12 +- .../lib/tsan/rtl/tsan_symbolize.cpp | 3 +- .../compiler-rt/lib/tsan/rtl/tsan_sync.cpp | 132 +- gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_sync.h | 80 +- .../compiler-rt/lib/tsan/rtl/tsan_trace.h | 217 +- .../lib/tsan/rtl/tsan_vector_clock.cpp | 126 + .../lib/tsan/rtl/tsan_vector_clock.h | 51 + .../compiler-rt/lib/tsan/tests/CMakeLists.txt | 27 +- .../lib/tsan/tests/rtl/tsan_mop.cpp | 34 +- .../lib/tsan/tests/rtl/tsan_mutex.cpp | 14 +- .../lib/tsan/tests/rtl/tsan_string.cpp | 12 +- .../lib/tsan/tests/rtl/tsan_test.cpp | 8 +- .../lib/tsan/tests/rtl/tsan_test_util.h | 7 + .../tsan/tests/rtl/tsan_test_util_posix.cpp | 44 +- .../lib/tsan/tests/rtl/tsan_thread.cpp | 6 +- .../lib/tsan/tests/unit/CMakeLists.txt | 4 +- .../lib/tsan/tests/unit/tsan_flags_test.cpp | 12 +- .../lib/tsan/tests/unit/tsan_ilist_test.cpp | 125 + .../lib/tsan/tests/unit/tsan_mman_test.cpp | 8 +- .../lib/tsan/tests/unit/tsan_shadow_test.cpp | 237 +- .../lib/tsan/tests/unit/tsan_stack_test.cpp | 15 +- .../lib/tsan/tests/unit/tsan_sync_test.cpp | 114 +- .../lib/tsan/tests/unit/tsan_trace_test.cpp | 341 +++ .../tsan/tests/unit/tsan_unit_test_main.cpp | 6 - .../tests/unit/tsan_vector_clock_test.cpp | 101 + gnu/llvm/compiler-rt/lib/ubsan/CMakeLists.txt | 57 +- gnu/llvm/compiler-rt/lib/ubsan/ubsan_diag.cpp | 20 +- .../compiler-rt/lib/ubsan/ubsan_handlers.cpp | 2 +- .../lib/ubsan/ubsan_handlers_cxx.cpp | 2 +- .../lib/ubsan/ubsan_handlers_cxx.h | 2 +- gnu/llvm/compiler-rt/lib/ubsan/ubsan_init.cpp | 7 +- .../lib/ubsan/ubsan_type_hash_itanium.cpp | 23 +- .../compiler-rt/lib/ubsan/ubsan_value.cpp | 6 +- .../lib/ubsan_minimal/CMakeLists.txt | 4 +- .../ubsan_minimal/ubsan_minimal_handlers.cpp | 41 +- gnu/llvm/compiler-rt/lib/xray/CMakeLists.txt | 35 +- .../compiler-rt/lib/xray/tests/CMakeLists.txt | 38 +- .../tests/unit/function_call_trie_test.cpp | 4 +- .../compiler-rt/lib/xray/xray_allocator.h | 16 +- .../compiler-rt/lib/xray/xray_basic_flags.h | 2 +- .../lib/xray/xray_basic_logging.cpp | 6 +- .../lib/xray/xray_buffer_queue.cpp | 2 +- gnu/llvm/compiler-rt/lib/xray/xray_flags.h | 2 +- .../compiler-rt/lib/xray/xray_hexagon.cpp | 168 ++ gnu/llvm/compiler-rt/lib/xray/xray_init.cpp | 2 +- .../compiler-rt/lib/xray/xray_interface.cpp | 13 +- .../lib/xray/xray_interface_internal.h | 8 - .../compiler-rt/lib/xray/xray_powerpc64.inc | 15 + .../compiler-rt/lib/xray/xray_profiling.cpp | 2 +- .../lib/xray/xray_trampoline_hexagon.S | 99 + gnu/llvm/compiler-rt/lib/xray/xray_tsc.h | 3 +- gnu/llvm/compiler-rt/lib/xray/xray_x86_64.cpp | 15 +- .../unittests/lit.common.unit.cfg.py | 17 +- .../unittests/lit.common.unit.configured.in | 19 +- .../utils/generate_netbsd_ioctls.awk | 4 +- .../utils/generate_netbsd_syscalls.awk | 2 +- gnu/llvm/compiler-rt/www/index.html | 12 +- gnu/llvm/compiler-rt/www/menu.html.incl | 2 +- 684 files changed, 36879 insertions(+), 15751 deletions(-) create mode 100644 gnu/llvm/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake create mode 100644 gnu/llvm/compiler-rt/cmake/Modules/CheckSectionExists.cmake create mode 100644 gnu/llvm/compiler-rt/cmake/crt-config-ix.cmake create mode 100644 gnu/llvm/compiler-rt/include/orc_rt/c_api.h create mode 100644 gnu/llvm/compiler-rt/include/profile/MIBEntryDef.inc create mode 100644 gnu/llvm/compiler-rt/include/profile/MemProfData.inc create mode 100644 gnu/llvm/compiler-rt/lib/asan/asan_rtl_static.cpp create mode 100644 gnu/llvm/compiler-rt/lib/asan/asan_rtl_x86_64.S create mode 100644 gnu/llvm/compiler-rt/lib/builtins/avr/divmodhi4.S create mode 100644 gnu/llvm/compiler-rt/lib/builtins/avr/divmodqi4.S create mode 100644 gnu/llvm/compiler-rt/lib/builtins/avr/exit.S create mode 100644 gnu/llvm/compiler-rt/lib/builtins/avr/mulhi3.S create mode 100644 gnu/llvm/compiler-rt/lib/builtins/avr/mulqi3.S create mode 100644 gnu/llvm/compiler-rt/lib/builtins/avr/udivmodhi4.S create mode 100644 gnu/llvm/compiler-rt/lib/builtins/avr/udivmodqi4.S create mode 100644 gnu/llvm/compiler-rt/lib/builtins/loongarch/fp_mode.c create mode 100644 gnu/llvm/compiler-rt/lib/builtins/riscv/fp_mode.c create mode 100644 gnu/llvm/compiler-rt/lib/builtins/truncdfbf2.c create mode 100644 gnu/llvm/compiler-rt/lib/builtins/truncsfbf2.c create mode 100644 gnu/llvm/compiler-rt/lib/fuzzer/FuzzerExtraCountersDarwin.cpp create mode 100644 gnu/llvm/compiler-rt/lib/fuzzer/FuzzerExtraCountersWindows.cpp create mode 100644 gnu/llvm/compiler-rt/lib/gwp_asan/tests/recoverable.cpp create mode 100644 gnu/llvm/compiler-rt/lib/hwasan/hwasan_preinit.cpp create mode 100644 gnu/llvm/compiler-rt/lib/hwasan/hwasan_setjmp_aarch64.S create mode 100644 gnu/llvm/compiler-rt/lib/hwasan/hwasan_setjmp_riscv64.S create mode 100644 gnu/llvm/compiler-rt/lib/hwasan/hwasan_setjmp_x86_64.S create mode 100644 gnu/llvm/compiler-rt/lib/hwasan/hwasan_tag_mismatch_riscv64.S create mode 100644 gnu/llvm/compiler-rt/lib/memprof/memprof_mibmap.cpp create mode 100644 gnu/llvm/compiler-rt/lib/memprof/memprof_mibmap.h create mode 100644 gnu/llvm/compiler-rt/lib/memprof/memprof_rawprofile.cpp create mode 100644 gnu/llvm/compiler-rt/lib/memprof/memprof_rawprofile.h create mode 100644 gnu/llvm/compiler-rt/lib/memprof/tests/CMakeLists.txt create mode 100644 gnu/llvm/compiler-rt/lib/memprof/tests/driver.cpp create mode 100644 gnu/llvm/compiler-rt/lib/memprof/tests/rawprofile.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/coff_platform.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/coff_platform.h create mode 100644 gnu/llvm/compiler-rt/lib/orc/coff_platform.per_jd.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/debug.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/debug.h create mode 100644 gnu/llvm/compiler-rt/lib/orc/dlfcn_wrapper.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/elfnix_platform.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/elfnix_platform.h create mode 100644 gnu/llvm/compiler-rt/lib/orc/elfnix_tls.aarch64.S create mode 100644 gnu/llvm/compiler-rt/lib/orc/elfnix_tls.x86-64.S create mode 100644 gnu/llvm/compiler-rt/lib/orc/interval_map.h create mode 100644 gnu/llvm/compiler-rt/lib/orc/interval_set.h create mode 100644 gnu/llvm/compiler-rt/lib/orc/macho_tlv.arm64.S create mode 100644 gnu/llvm/compiler-rt/lib/orc/string_pool.h create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/CMakeLists.txt create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/tools/CMakeLists.txt create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/tools/orc-rt-executor.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/unit/CMakeLists.txt create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/unit/adt_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/unit/c_api_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/unit/endian_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/unit/error_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/unit/executor_address_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/unit/extensible_rtti_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/unit/interval_map_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/unit/interval_set_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/unit/orc_unit_test_main.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/unit/simple_packed_serialization_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/unit/string_pool_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/orc/tests/unit/wrapper_function_utils_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_loongarch64.inc.S create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_dense_map.h create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_dense_map_info.h create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_flat_map.h create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_leb128.h create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_lzw.h create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_solaris.h create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.cpp create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.h create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_hexagon.inc create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_loongarch64.inc create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/tests/sanitizer_addrhashmap_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/tests/sanitizer_dense_map_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/tests/sanitizer_flat_map_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/tests/sanitizer_hash_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/tests/sanitizer_leb128_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/tests/sanitizer_lzw_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/sanitizer_common/tests/sanitizer_stack_store_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/scudo/standalone/rss_limit_checker.cpp create mode 100644 gnu/llvm/compiler-rt/lib/scudo/standalone/rss_limit_checker.h create mode 100644 gnu/llvm/compiler-rt/lib/tsan/rtl/CMakeLists.txt create mode 100644 gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_ilist.h create mode 100644 gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_interface.inc create mode 100644 gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_rtl_access.cpp create mode 100644 gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_rtl_loongarch64.S create mode 100644 gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_shadow.h create mode 100644 gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_vector_clock.cpp create mode 100644 gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_vector_clock.h create mode 100644 gnu/llvm/compiler-rt/lib/tsan/tests/unit/tsan_ilist_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/tsan/tests/unit/tsan_trace_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/tsan/tests/unit/tsan_vector_clock_test.cpp create mode 100644 gnu/llvm/compiler-rt/lib/xray/xray_hexagon.cpp create mode 100644 gnu/llvm/compiler-rt/lib/xray/xray_trampoline_hexagon.S diff --git a/gnu/llvm/compiler-rt/CMakeLists.txt b/gnu/llvm/compiler-rt/CMakeLists.txt index e12d1eb1ceb..8a13508fcb9 100644 --- a/gnu/llvm/compiler-rt/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/CMakeLists.txt @@ -10,12 +10,23 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR COMPILER_RT_STANDALONE project(CompilerRT C CXX ASM) set(COMPILER_RT_STANDALONE_BUILD TRUE) set_property(GLOBAL PROPERTY USE_FOLDERS ON) + if ("${CMAKE_VERSION}" VERSION_LESS "3.20.0") + message(WARNING + "Your CMake version is ${CMAKE_VERSION}. Starting with LLVM 17.0.0, the " + "minimum version of CMake required to build LLVM will become 3.20.0, and " + "using an older CMake will become an error. Please upgrade your CMake to " + "at least 3.20.0 now to avoid issues in the future!") + endif() endif() +set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake") + # Add path for custom compiler-rt modules. list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_SOURCE_DIR}/cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" + "${LLVM_COMMON_CMAKE_UTILS}" + "${LLVM_COMMON_CMAKE_UTILS}/Modules" ) if(CMAKE_CONFIGURATION_TYPES) @@ -24,11 +35,15 @@ else() set(CMAKE_CFG_RESOLVED_INTDIR "") endif() +include(SetPlatformToolchainTools) include(base-config-ix) include(CompilerRTUtils) +include(CMakeDependentOption) option(COMPILER_RT_BUILD_BUILTINS "Build builtins" ON) mark_as_advanced(COMPILER_RT_BUILD_BUILTINS) +option(COMPILER_RT_DISABLE_AARCH64_FMV "Disable AArch64 Function Multi Versioning support" OFF) +mark_as_advanced(COMPILER_RT_DISABLE_AARCH64_FMV) option(COMPILER_RT_BUILD_CRT "Build crtbegin.o/crtend.o" ON) mark_as_advanced(COMPILER_RT_BUILD_CRT) option(COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY "Use eh_frame in crtbegin.o/crtend.o" ON) @@ -47,25 +62,16 @@ option(COMPILER_RT_BUILD_XRAY_NO_PREINIT "Build xray with no preinit patching" O mark_as_advanced(COMPILER_RT_BUILD_XRAY_NO_PREINIT) option(COMPILER_RT_BUILD_ORC "Build ORC runtime" ON) mark_as_advanced(COMPILER_RT_BUILD_ORC) +option(COMPILER_RT_BUILD_GWP_ASAN "Build GWP-ASan, and link it into SCUDO" ON) +mark_as_advanced(COMPILER_RT_BUILD_GWP_ASAN) +option(COMPILER_RT_ENABLE_CET "Build Compiler RT with CET enabled" OFF) -set(COMPILER_RT_ASAN_SHADOW_SCALE "" - CACHE STRING "Override the shadow scale to be used in ASan runtime") - -if (NOT COMPILER_RT_ASAN_SHADOW_SCALE STREQUAL "") - # Check that the shadow scale value is valid. - if (NOT (COMPILER_RT_ASAN_SHADOW_SCALE GREATER -1 AND - COMPILER_RT_ASAN_SHADOW_SCALE LESS 8)) - message(FATAL_ERROR " - Invalid ASan Shadow Scale '${COMPILER_RT_ASAN_SHADOW_SCALE}'.") - endif() - - set(COMPILER_RT_ASAN_SHADOW_SCALE_LLVM_FLAG - -mllvm -asan-mapping-scale=${COMPILER_RT_ASAN_SHADOW_SCALE}) - set(COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION - ASAN_SHADOW_SCALE=${COMPILER_RT_ASAN_SHADOW_SCALE}) - set(COMPILER_RT_ASAN_SHADOW_SCALE_FLAG - -D${COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION}) -endif() +option(COMPILER_RT_SCUDO_STANDALONE_SYSROOT_PATH "Set custom sysroot for building SCUDO standalone" OFF) +mark_as_advanced(COMPILER_RT_SCUDO_STANDALONE_SYSROOT_PATH) +option(COMPILER_RT_SCUDO_STANDALONE_BUILD_SHARED "Build SCUDO standalone for shared libraries" ON) +mark_as_advanced(COMPILER_RT_SCUDO_STANDALONE_BUILD_SHARED) +option(COMPILER_RT_BUILD_SCUDO_STANDALONE_WITH_LLVM_LIBC "Build SCUDO standalone with LLVM's libc headers" OFF) +mark_as_advanced(COMPILER_RT_BUILD_SCUDO_STANDALONE_WITH_LLVM_LIBC) if(FUCHSIA) set(COMPILER_RT_HWASAN_WITH_INTERCEPTORS_DEFAULT OFF) @@ -78,7 +84,13 @@ set(COMPILER_RT_BAREMETAL_BUILD OFF CACHE BOOL "Build for a bare-metal target.") if (COMPILER_RT_STANDALONE_BUILD) - load_llvm_config() + set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to") + set(CMAKE_CXX_STANDARD_REQUIRED YES) + set(CMAKE_CXX_EXTENSIONS NO) + + if (NOT LLVM_RUNTIMES_BUILD) + load_llvm_config() + endif() if (TARGET intrinsics_gen) # Loading the llvm config causes this target to be imported so place it # under the appropriate folder in an IDE. @@ -121,6 +133,20 @@ if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*hf$") CHECK_SYMBOL_EXISTS (__thumb__ "" COMPILER_RT_ARM_THUMB) endif() endif() +if (${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "^mips") + CHECK_SYMBOL_EXISTS (_MIPS_ARCH_MIPS32R6 "" COMPILER_RT_MIPS32R6) + CHECK_SYMBOL_EXISTS (_MIPS_ARCH_MIPS64R6 "" COMPILER_RT_MIPS64R6) + CHECK_SYMBOL_EXISTS (__mips64 "" COMPILER_RT_MIPS_64) + CHECK_SYMBOL_EXISTS (__MIPSEL__ "" COMPILER_RT_MIPS_EL) + if ("${COMPILER_RT_MIPS_64}") + set(COMPILER_RT_DEFAULT_TARGET_ARCH "mips64") + else() + set(COMPILER_RT_DEFAULT_TARGET_ARCH "mips") + endif() + if ("${COMPILER_RT_MIPS_EL}") + set(COMPILER_RT_DEFAULT_TARGET_ARCH "${COMPILER_RT_DEFAULT_TARGET_ARCH}el") + endif() +endif() if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*android.*") set(ANDROID 1) string(REGEX MATCH "-target(=| +)[^ ]+android[a-z]*([0-9]+)" ANDROID_API_LEVEL "${CMAKE_C_FLAGS}") @@ -133,11 +159,11 @@ set(COMPILER_RT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) pythonize_bool(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR) -# We support running instrumented tests when we're not cross compiling +# We support running instrumented tests when we're not cross-compiling # and target a UNIX-like system or Windows. # We can run tests on Android even when we are cross-compiling. -if(("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND (UNIX OR WIN32)) OR ANDROID - OR COMPILER_RT_EMULATOR) +if(("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "${CMAKE_SYSTEM_NAME}" AND (UNIX OR WIN32)) + OR ANDROID OR COMPILER_RT_EMULATOR) option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" ON) else() option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" OFF) @@ -209,6 +235,7 @@ endmacro() # This is either directly the C++ ABI library or the full C++ library # which pulls in the ABI transitively. +# TODO: Mark this as internal flag, most users should use COMPILER_RT_CXX_LIBRARY. set(SANITIZER_CXX_ABI "default" CACHE STRING "Specify C++ ABI library to use.") set(CXXABIS none default libstdc++ libc++ libcxxabi) @@ -216,12 +243,18 @@ set_property(CACHE SANITIZER_CXX_ABI PROPERTY STRINGS ;${CXXABIS}) handle_default_cxx_lib(SANITIZER_CXX_ABI) # This needs to be a full C++ library for linking gtest and unit tests. +# TODO: Mark this as internal flag, most users should use COMPILER_RT_CXX_LIBRARY. set(SANITIZER_TEST_CXX "default" CACHE STRING "Specify C++ library to use for tests.") set(CXXLIBS none default libstdc++ libc++) set_property(CACHE SANITIZER_TEST_CXX PROPERTY STRINGS ;${CXXLIBS}) handle_default_cxx_lib(SANITIZER_TEST_CXX) +option(COMPILER_RT_USE_LLVM_UNWINDER "Use the LLVM unwinder." OFF) +cmake_dependent_option(COMPILER_RT_ENABLE_STATIC_UNWINDER + "Statically link the LLVM unwinder." OFF + "COMPILER_RT_USE_LLVM_UNWINDER" OFF) + set(DEFAULT_SANITIZER_USE_STATIC_LLVM_UNWINDER OFF) if (FUCHSIA) set(DEFAULT_SANITIZER_USE_STATIC_LLVM_UNWINDER ON) @@ -231,6 +264,7 @@ endif() option(SANITIZER_USE_STATIC_LLVM_UNWINDER "Use static LLVM unwinder." ${DEFAULT_SANITIZER_USE_STATIC_LLVM_UNWINDER}) +pythonize_bool(SANITIZER_USE_STATIC_LLVM_UNWINDER) set(DEFAULT_SANITIZER_USE_STATIC_CXX_ABI OFF) if (DEFINED LIBCXXABI_ENABLE_SHARED AND NOT LIBCXXABI_ENABLE_SHARED) @@ -239,6 +273,25 @@ endif() option(SANITIZER_USE_STATIC_CXX_ABI "Use static libc++abi." ${DEFAULT_SANITIZER_USE_STATIC_CXX_ABI}) +pythonize_bool(SANITIZER_USE_STATIC_CXX_ABI) + +set(DEFAULT_SANITIZER_USE_STATIC_TEST_CXX OFF) +if (DEFINED LIBCXX_ENABLE_SHARED AND NOT LIBCXX_ENABLE_SHARED) + set(DEFAULT_SANITIZER_USE_STATIC_TEST_CXX ON) +endif() + +option(SANITIZER_USE_STATIC_TEST_CXX + "Use static libc++ for tests." ${DEFAULT_SANITIZER_USE_STATIC_TEST_CXX}) +pythonize_bool(SANITIZER_USE_STATIC_TEST_CXX) + +set(COMPILER_RT_SUPPORTED_CXX_LIBRARIES none default libcxx) +set(COMPILER_RT_CXX_LIBRARY "default" CACHE STRING "Specify C++ library to use. Supported values are ${COMPILER_RT_SUPPORTED_CXX_LIBRARIES}.") +if (NOT "${COMPILER_RT_CXX_LIBRARY}" IN_LIST COMPILER_RT_SUPPORTED_CXX_LIBRARIES) + message(FATAL_ERROR "Unsupported C++ library: '${COMPILER_RT_CXX_LIBRARY}'. Supported values are ${COMPILER_RT_SUPPORTED_CXX_LIBRARIES}.") +endif() +cmake_dependent_option(COMPILER_RT_STATIC_CXX_LIBRARY + "Statically link the C++ library." OFF + "COMPILER_RT_CXX_LIBRARY" OFF) set(DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY OFF) if (FUCHSIA) @@ -254,6 +307,14 @@ include(config-ix) # Setup Compiler Flags #================================ +# fcf-protection is a gcc/clang option for CET support on Linux platforms. +# We need to handle MSVC CET option on Windows platforms. +if (NOT MSVC) + if (COMPILER_RT_ENABLE_CET AND NOT COMPILER_RT_HAS_FCF_PROTECTION_FLAG) + message(FATAL_ERROR "Compiler used to build compiler-rt doesn't support CET!") + endif() +endif() + if(MSVC) # Override any existing /W flags with /W4. This is what LLVM does. Failing to # remove other /W[0-4] flags will result in a warning about overriding a @@ -271,8 +332,6 @@ if(COMPILER_RT_ENABLE_WERROR) append_string_if(COMPILER_RT_HAS_WX_FLAG /WX CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() -append_string_if(COMPILER_RT_HAS_STD_CXX14_FLAG -std=c++14 CMAKE_CXX_FLAGS) - # Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP. if(NOT COMPILER_RT_HAS_FUNC_SYMBOL) add_definitions(-D__func__=__FUNCTION__) @@ -307,8 +366,11 @@ if(NOT COMPILER_RT_ENABLE_PGO) endif() if(LLVM_BUILD_INSTRUMENTED MATCHES IR AND COMPILER_RT_HAS_FNO_PROFILE_GENERATE_FLAG) list(APPEND SANITIZER_COMMON_CFLAGS "-fno-profile-generate") - elseif(LLVM_BUILD_INSTRUMENTED AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG) + elseif((LLVM_BUILD_INSTRUMENTED OR LLVM_BUILD_INSTRUMENTED_COVERAGE) AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG) list(APPEND SANITIZER_COMMON_CFLAGS "-fno-profile-instr-generate") + if(LLVM_BUILD_INSTRUMENTED_COVERAGE AND COMPILER_RT_HAS_FNO_COVERAGE_MAPPING_FLAG) + list(APPEND SANITIZER_COMMON_CFLAGS "-fno-coverage-mapping") + endif() endif() endif() @@ -359,16 +421,12 @@ endif() append_list_if(COMPILER_RT_DEBUG -DSANITIZER_DEBUG=1 SANITIZER_COMMON_CFLAGS) -if(CMAKE_CXX_COMPILER_ID MATCHES Clang) - list(APPEND THREAD_SAFETY_FLAGS - "-Werror=thread-safety" - "-Werror=thread-safety-reference" - "-Werror=thread-safety-beta" - ) - list(APPEND SANITIZER_COMMON_CFLAGS ${THREAD_SAFETY_FLAGS}) - string(REPLACE ";" " " thread_safety_flags_space_sep "${THREAD_SAFETY_FLAGS}") - string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " ${thread_safety_flags_space_sep}") -endif() +append_list_if(COMPILER_RT_HAS_WTHREAD_SAFETY_FLAG -Wthread-safety THREAD_SAFETY_FLAGS) +append_list_if(COMPILER_RT_HAS_WTHREAD_SAFETY_REFERENCE_FLAG -Wthread-safety-reference THREAD_SAFETY_FLAGS) +append_list_if(COMPILER_RT_HAS_WTHREAD_SAFETY_BETA_FLAG -Wthread-safety-beta THREAD_SAFETY_FLAGS) +list(APPEND SANITIZER_COMMON_CFLAGS ${THREAD_SAFETY_FLAGS}) +string(REPLACE ";" " " thread_safety_flags_space_sep "${THREAD_SAFETY_FLAGS}") +string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " ${thread_safety_flags_space_sep}") # If we're using MSVC, # always respect the optimization flags set by CMAKE_BUILD_TYPE instead. @@ -376,7 +434,7 @@ if (NOT MSVC) # Build with optimization, unless we're in debug mode. if(COMPILER_RT_DEBUG) - list(APPEND SANITIZER_COMMON_CFLAGS -O0) + list(APPEND SANITIZER_COMMON_CFLAGS -O1) else() list(APPEND SANITIZER_COMMON_CFLAGS -O3) endif() @@ -413,6 +471,13 @@ if(MSVC) string(REGEX REPLACE "(^| )/Z[i7I]($| )" " /Z7 " "${var_to_update}" "${${var_to_update}}") endforeach() +elseif(APPLE) + # On Apple platforms use full debug info (i.e. not `-gline-tables-only`) + # for all build types so that the runtime can be debugged. + if(NOT COMPILER_RT_HAS_G_FLAG) + message(FATAL_ERROR "-g is not supported by host compiler") + endif() + list(APPEND SANITIZER_COMMON_CFLAGS -g) elseif(COMPILER_RT_HAS_GLINE_TABLES_ONLY_FLAG AND NOT COMPILER_RT_DEBUG) list(APPEND SANITIZER_COMMON_CFLAGS -gline-tables-only) elseif(COMPILER_RT_HAS_G_FLAG) @@ -429,6 +494,7 @@ endif() append_list_if(COMPILER_RT_HAS_WGNU_FLAG -Wno-gnu SANITIZER_COMMON_CFLAGS) append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros SANITIZER_COMMON_CFLAGS) append_list_if(COMPILER_RT_HAS_WC99_EXTENSIONS_FLAG -Wno-c99-extensions SANITIZER_COMMON_CFLAGS) +# format-pedantic warns about passing T* for %p, which is not useful. append_list_if(COMPILER_RT_HAS_WD4146_FLAG /wd4146 SANITIZER_COMMON_CFLAGS) append_list_if(COMPILER_RT_HAS_WD4291_FLAG /wd4291 SANITIZER_COMMON_CFLAGS) append_list_if(COMPILER_RT_HAS_WD4391_FLAG /wd4391 SANITIZER_COMMON_CFLAGS) @@ -437,10 +503,33 @@ append_list_if(COMPILER_RT_HAS_WD4800_FLAG /wd4800 SANITIZER_COMMON_CFLAGS) append_list_if(MINGW -fms-extensions SANITIZER_COMMON_CFLAGS) +# When lsan scans the stack for detecting reachable pointers, it's possible for +# a leaked pointer, which was pushed to the stack on an earlier function call, +# to still exist on the stack when doing a leak check if that part of the stack +# was not overwritten. In particular, if there's any uninitialized data in the +# lsan runtime, and the SP we start from is sufficiently deep into the runtime, +# then a leaked pointer could be marked as reachable. Such instances could be +# mitigated by clobbering any uninitialized data. Note that this won't cover +# all possible uninitialized stack contents, such as those used for register +# spill slots, unused portions for alignment, or even local variables not +# yet in scope at a certain point in the function. +# +# Note that this type of issue was discovered with lsan, but can apply to other +# sanitizers. +append_list_if(COMPILER_RT_HAS_TRIVIAL_AUTO_INIT -ftrivial-auto-var-init=pattern SANITIZER_COMMON_CFLAGS) + # Set common link flags. -append_list_if(COMPILER_RT_HAS_NODEFAULTLIBS_FLAG -nodefaultlibs SANITIZER_COMMON_LINK_FLAGS) +# TODO: We should consider using the same model as libc++, that is use either +# -nostdlib++ and --unwindlib=none if supported, or -nodefaultlibs otherwise. +append_list_if(C_SUPPORTS_NODEFAULTLIBS_FLAG -nodefaultlibs SANITIZER_COMMON_LINK_FLAGS) append_list_if(COMPILER_RT_HAS_Z_TEXT -Wl,-z,text SANITIZER_COMMON_LINK_FLAGS) +# Only necessary for 32-bit SPARC. Solaris 11.2+ ld uses -z ignore/-z record +# natively, but supports --as-needed/--no-as-needed for GNU ld compatibility. +if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "sparc") + list(APPEND SANITIZER_COMMON_LINK_LIBS -Wl,--as-needed atomic -Wl,--no-as-needed) +endif() + if (COMPILER_RT_USE_BUILTINS_LIBRARY) string(REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") else() @@ -485,26 +574,68 @@ string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} list(APPEND COMPILER_RT_COMMON_CFLAGS ${stdlib_flag}) list(APPEND COMPILER_RT_COMMON_LINK_FLAGS ${stdlib_flag}) -macro(append_libcxx_libs var) - if (${var}_INTREE) - if (SANITIZER_USE_STATIC_LLVM_UNWINDER AND (TARGET unwind_static OR HAVE_LIBUNWIND)) - list(APPEND ${var}_LIBRARIES unwind_static) - elseif (TARGET unwind_shared OR HAVE_LIBUNWIND) - list(APPEND ${var}_LIBRARIES unwind_shared) - endif() +# TODO: There's a lot of duplication across lib/*/tests/CMakeLists.txt files, +# move some of the common flags to COMPILER_RT_UNITTEST_CFLAGS. - if (SANITIZER_USE_STATIC_CXX_ABI AND (TARGET cxxabi_static OR HAVE_LIBCXXABI)) - list(APPEND ${var}_LIBRARIES cxxabi_static) - elseif (TARGET cxxabi_shared OR HAVE_LIBCXXABI) - list(APPEND ${var}_LIBRARIES cxxabi_shared) - endif() +# Unittests need access to C++ standard library. +string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " ${stdlib_flag}") + +# When cross-compiling, COMPILER_RT_TEST_COMPILER_CFLAGS help in compilation +# and linking of unittests. +string(REPLACE " " ";" COMPILER_RT_UNITTEST_CFLAGS "${COMPILER_RT_TEST_COMPILER_CFLAGS}") +set(COMPILER_RT_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_CFLAGS}) + +if(COMPILER_RT_USE_LLVM_UNWINDER) + # We're linking directly against the libunwind that we're building so don't + # try to link in the toolchain's default libunwind which may be missing. + append_list_if(CXX_SUPPORTS_UNWINDLIB_NONE_FLAG --unwindlib=none COMPILER_RT_COMMON_LINK_FLAGS) + append_list_if(CXX_SUPPORTS_UNWINDLIB_NONE_FLAG --unwindlib=none COMPILER_RT_UNITTEST_LINK_FLAGS) + if (COMPILER_RT_ENABLE_STATIC_UNWINDER) + list(APPEND COMPILER_RT_UNWINDER_LINK_LIBS "$") else() - append_list_if(COMPILER_RT_HAS_LIBCXX c++ ${var}_LIBRARIES) + list(APPEND COMPILER_RT_UNWINDER_LINK_LIBS "$,unwind_shared,unwind_static>>") endif() -endmacro() +endif() + +if (COMPILER_RT_CXX_LIBRARY STREQUAL "libcxx") + # We are using the in-tree libc++ so avoid including the default one. + append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ COMPILER_RT_COMMON_CFLAGS) + append_list_if(COMPILER_RT_HAS_NOSTDLIBXX_FLAG -nostdlib++ COMPILER_RT_COMMON_LINK_FLAGS) + # Use the in-tree libc++ through explicit include and library paths. + set(COMPILER_RT_CXX_CFLAGS "$<$:$,/imsvc,-isystem>$,$$,/imsvc,-isystem>>>") + if (COMPILER_RT_STATIC_CXX_LIBRARY) + set(COMPILER_RT_CXX_LINK_LIBS "$") + else() + set(COMPILER_RT_CXX_LINK_LIBS "$,cxx_shared,cxx_static>>") + endif() +elseif (COMPILER_RT_CXX_LIBRARY STREQUAL "none") + # We aren't using any C++ standard library so avoid including the default one. + append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ COMPILER_RT_COMMON_CFLAGS) + append_list_if(COMPILER_RT_HAS_NOSTDLIBXX_FLAG -nostdlib++ COMPILER_RT_COMMON_LINK_FLAGS) +else() + # Nothing to be done for `default`. +endif() if (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libc++") - append_libcxx_libs(SANITIZER_CXX_ABI) + if (SANITIZER_CXX_ABI_INTREE) + # TODO: We don't need to add --unwindlib=none to SANITIZER_COMMON_LINK_FLAGS + # because we added -nodefaultlibs there earlier, and adding would result in + # a warning, but if we switch to -nostdlib++, we would need to add it here. + # append_list_if(CXX_SUPPORTS_UNWINDLIB_NONE_FLAG --unwindlib=none SANITIZER_COMMON_LINK_FLAGS) + if(SANITIZER_USE_STATIC_CXX_ABI) + if(TARGET libcxx-abi-static) + set(SANITIZER_CXX_ABI_LIBRARIES libcxx-abi-static) + endif() + else() + if(TARGET libcxx-abi-shared) + set(SANITIZER_CXX_ABI_LIBRARIES libcxx-abi-shared) + elseif(TARGET libcxx-abi-static) + set(SANITIZER_CXX_ABI_LIBRARIES libcxx-abi-static) + endif() + endif() + else() + append_list_if(COMPILER_RT_HAS_LIBCXX c++ SANITIZER_CXX_ABI_LIBRARIES) + endif() elseif (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libcxxabi") list(APPEND SANITIZER_CXX_ABI_LIBRARIES "c++abi") elseif (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libstdc++") @@ -512,24 +643,31 @@ elseif (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libstdc++") endif() if (SANITIZER_TEST_CXX_LIBNAME STREQUAL "libc++") - append_libcxx_libs(SANITIZER_TEST_CXX) + if (SANITIZER_TEST_CXX_INTREE) + list(APPEND SANITIZER_TEST_CXX_CFLAGS "$<$:$,/imsvc,-isystem>$,$$,/imsvc,-isystem>>>") + if (SANITIZER_USE_STATIC_TEST_CXX) + list(APPEND SANITIZER_TEST_CXX_LIBRARIES "$") + else() + list(APPEND SANITIZER_TEST_CXX_LIBRARIES "$,cxx_shared,cxx_static>>") + endif() + # We are using the in tree libc++ so avoid including the default one. + append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ COMPILER_RT_UNITTEST_CFLAGS) + append_list_if(COMPILER_RT_HAS_NOSTDLIBXX_FLAG -nostdlib++ COMPILER_RT_UNITTEST_LINK_FLAGS) + else() + append_list_if(COMPILER_RT_HAS_LIBCXX -lc++ SANITIZER_TEST_CXX_LIBRARIES) + endif() elseif (SANITIZER_TEST_CXX_LIBNAME STREQUAL "libstdc++") - append_list_if(COMPILER_RT_HAS_LIBSTDCXX stdc++ SANITIZER_TEST_CXX_LIBRARIES) + append_list_if(COMPILER_RT_HAS_LIBSTDCXX -lstdc++ SANITIZER_TEST_CXX_LIBRARIES) endif() -# TODO: There's a lot of duplication across lib/*/tests/CMakeLists.txt files, -# move some of the common flags to COMPILER_RT_UNITTEST_CFLAGS. - -# Unittests need access to C++ standard library. -string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " ${stdlib_flag}") - -# When cross-compiling, COMPILER_RT_TEST_COMPILER_CFLAGS help in compilation -# and linking of unittests. -string(REPLACE " " ";" COMPILER_RT_UNITTEST_CFLAGS "${COMPILER_RT_TEST_COMPILER_CFLAGS}") -set(COMPILER_RT_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_CFLAGS}) - # Unittests support. -set(COMPILER_RT_GTEST_PATH ${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest) +# FIXME: When compiler-rt is build using -DLLVM_BUILD_EXTERNAL_COMPILER_RT=ON, then +# The LLVM_THIRD_PARTY_DIR variable is not set. +if (NOT LLVM_THIRD_PARTY_DIR) + set(LLVM_THIRD_PARTY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../third-party") +endif() + +set(COMPILER_RT_GTEST_PATH ${LLVM_THIRD_PARTY_DIR}/unittest/googletest) set(COMPILER_RT_GTEST_SOURCE ${COMPILER_RT_GTEST_PATH}/src/gtest-all.cc) set(COMPILER_RT_GTEST_CFLAGS -DGTEST_NO_LLVM_SUPPORT=1 @@ -537,17 +675,9 @@ set(COMPILER_RT_GTEST_CFLAGS -I${COMPILER_RT_GTEST_PATH}/include -I${COMPILER_RT_GTEST_PATH} ) -if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - # FreeBSD has its pthread functions marked with thread safety annotations, but - # googletest is not compatible with such annotations. Disable the thread - # safety warnings-as-errors until googletest has been fixed. - list(APPEND NO_THREAD_SAFETY_FLAGS ${THREAD_SAFETY_FLAGS}) - list(TRANSFORM NO_THREAD_SAFETY_FLAGS REPLACE "error=" "no-") - list(APPEND COMPILER_RT_GTEST_CFLAGS ${NO_THREAD_SAFETY_FLAGS}) -endif() # Mocking support. -set(COMPILER_RT_GMOCK_PATH ${LLVM_MAIN_SRC_DIR}/utils/unittest/googlemock) +set(COMPILER_RT_GMOCK_PATH ${LLVM_THIRD_PARTY_DIR}/unittest/googlemock) set(COMPILER_RT_GMOCK_SOURCE ${COMPILER_RT_GMOCK_PATH}/src/gmock-all.cc) set(COMPILER_RT_GMOCK_CFLAGS -DGTEST_NO_LLVM_SUPPORT=1 @@ -556,6 +686,9 @@ set(COMPILER_RT_GMOCK_CFLAGS -I${COMPILER_RT_GMOCK_PATH} ) +if(COMPILER_RT_HAS_G_FLAG) + list(APPEND COMPILER_RT_UNITTEST_CFLAGS -g) +endif() append_list_if(COMPILER_RT_DEBUG -DSANITIZER_DEBUG=1 COMPILER_RT_UNITTEST_CFLAGS) append_list_if(COMPILER_RT_HAS_WCOVERED_SWITCH_DEFAULT_FLAG -Wno-covered-switch-default COMPILER_RT_UNITTEST_CFLAGS) append_list_if(COMPILER_RT_HAS_WSUGGEST_OVERRIDE_FLAG -Wno-suggest-override COMPILER_RT_UNITTEST_CFLAGS) @@ -579,15 +712,6 @@ if (CMAKE_LINKER MATCHES "link.exe$") set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /IGNORE:4221") endif() -if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") - set(CMAKE_C_ARCHIVE_CREATE " -X32_64 qc ") - set(CMAKE_CXX_ARCHIVE_CREATE " -X32_64 qc ") - set(CMAKE_C_ARCHIVE_APPEND " -X32_64 q ") - set(CMAKE_CXX_ARCHIVE_APPEND " -X32_64 q ") - set(CMAKE_C_ARCHIVE_FINISH " -X32_64 ") - set(CMAKE_CXX_ARCHIVE_FINISH " -X32_64 ") -endif() - add_subdirectory(include) option(COMPILER_RT_USE_LIBCXX @@ -634,9 +758,6 @@ if(ANDROID) set(COMPILER_RT_TEST_USE_LLD TRUE) append_list_if(COMPILER_RT_HAS_FUSE_LD_LLD_FLAG -fuse-ld=lld SANITIZER_COMMON_LINK_FLAGS) append_list_if(COMPILER_RT_HAS_LLD -fuse-ld=lld COMPILER_RT_UNITTEST_LINK_FLAGS) - if(COMPILER_RT_HAS_FUSE_LD_LLD_FLAG) - set(COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT FALSE) - endif() endif() pythonize_bool(COMPILER_RT_HAS_LLD) pythonize_bool(COMPILER_RT_TEST_USE_LLD) diff --git a/gnu/llvm/compiler-rt/CODE_OWNERS.TXT b/gnu/llvm/compiler-rt/CODE_OWNERS.TXT index 125487816bc..80f7a93efc3 100644 --- a/gnu/llvm/compiler-rt/CODE_OWNERS.TXT +++ b/gnu/llvm/compiler-rt/CODE_OWNERS.TXT @@ -8,33 +8,41 @@ beautification by scripts. The fields are: name (N), email (E), web-address (W), PGP key ID and fingerprint (P), description (D), and snail-mail address (S). +N: Saleem Abdulrasool +E: compnerd@compnerd.org +D: builtins library + +N: Vitaly Buka +E: vitalybuka@google.com +D: Sanitizers + N: Peter Collingbourne E: peter@pcc.me.uk -D: DataFlowSanitizer +D: CFI, SafeStack -N: Daniel Dunbar -E: daniel@zuster.org -D: Makefile build +N: Lang Hames +E: lhames@gmail.com +D: ORC -N: Timur Iskhodzhanov -E: timurrrr@google.com -D: AddressSanitizer for Windows +N: Petr Hosek +E: phosek@google.com +D: CRT, CMake build -N: Howard Hinnant -E: howard.hinnant@gmail.com -D: builtins library +N: Teresa Johnson +E: tejohnson@google.com +D: MemProf + +N: Mitch Phillips +E: mitchp@google.com +D: GWP ASAN N: Alexander Potapenko E: glider@google.com -D: MacOS/iOS port of sanitizers - -N: Alexey Samsonov -E: samsonov@google.com -D: CMake build, test suite +D: Sanitizers N: Kostya Serebryany E: kcc@google.com -D: AddressSanitizer, sanitizer_common, porting sanitizers to another platforms, LeakSanitizer +D: AddressSanitizer, sanitizer_common, LeakSanitizer, LibFuzzer N: Richard Smith E: richard-llvm@metafoo.co.uk diff --git a/gnu/llvm/compiler-rt/cmake/Modules/AddCompilerRT.cmake b/gnu/llvm/compiler-rt/cmake/Modules/AddCompilerRT.cmake index bc69ec95c41..045221312a8 100644 --- a/gnu/llvm/compiler-rt/cmake/Modules/AddCompilerRT.cmake +++ b/gnu/llvm/compiler-rt/cmake/Modules/AddCompilerRT.cmake @@ -2,6 +2,12 @@ include(ExternalProject) include(CompilerRTUtils) include(HandleCompilerRT) +# CMP0114: ExternalProject step targets fully adopt their steps. +# New in CMake 3.19: https://cmake.org/cmake/help/latest/policy/CMP0114.html +if(POLICY CMP0114) + cmake_policy(SET CMP0114 OLD) +endif() + function(set_target_output_directories target output_dir) # For RUNTIME_OUTPUT_DIRECTORY variable, Multi-configuration generators # append a per-configuration subdirectory to the specified directory. @@ -77,6 +83,16 @@ function(add_compiler_rt_object_libraries name) list(REMOVE_ITEM target_flags "-msse3") endif() + # Build the macOS sanitizers with Mac Catalyst support. + if (APPLE AND + "${COMPILER_RT_ENABLE_MACCATALYST}" AND + "${libname}" MATCHES ".*\.osx.*") + foreach(arch ${LIB_ARCHS_${libname}}) + list(APPEND target_flags + "SHELL:-target ${arch}-apple-macos${DARWIN_osx_MIN_VER} -darwin-target-variant ${arch}-apple-ios13.1-macabi") + endforeach() + endif() + set_target_compile_flags(${libname} ${extra_cflags_${libname}} ${target_flags}) set_property(TARGET ${libname} APPEND PROPERTY @@ -128,13 +144,16 @@ macro(set_output_name output name arch) if(COMPILER_RT_DEFAULT_TARGET_ONLY) set(triple "${COMPILER_RT_DEFAULT_TARGET_TRIPLE}") else() - set(triple "${TARGET_TRIPLE}") + set(triple "${LLVM_TARGET_TRIPLE}") endif() - # When using arch-suffixed runtime library names, clang only looks for - # libraries named "arm" or "armhf", see getArchNameForCompilerRTLib in - # clang. Therefore, try to inspect both the arch name and the triple - # if it seems like we're building an armhf target. - if ("${arch}" MATCHES "hf$" OR "${triple}" MATCHES "hf$") + # Except for baremetal, when using arch-suffixed runtime library names, + # clang only looks for libraries named "arm" or "armhf", see + # getArchNameForCompilerRTLib in clang. Therefore, try to inspect both + # the arch name and the triple if it seems like we're building an armhf + # target. + if (COMPILER_RT_BAREMETAL_BUILD) + set(${output} "${name}-${arch}${COMPILER_RT_OS_SUFFIX}") + elseif ("${arch}" MATCHES "hf$" OR "${triple}" MATCHES "hf$") set(${output} "${name}-armhf${COMPILER_RT_OS_SUFFIX}") else() set(${output} "${name}-arm${COMPILER_RT_OS_SUFFIX}") @@ -188,8 +207,11 @@ function(add_compiler_rt_runtime name type) endif() if(LLVM_BUILD_INSTRUMENTED MATCHES IR AND COMPILER_RT_HAS_FNO_PROFILE_GENERATE_FLAG) list(APPEND NO_PGO_FLAGS "-fno-profile-generate") - elseif(LLVM_BUILD_INSTRUMENTED AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG) + elseif((LLVM_BUILD_INSTRUMENTED OR LLVM_BUILD_INSTRUMENTED_COVERAGE) AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG) list(APPEND NO_PGO_FLAGS "-fno-profile-instr-generate") + if(LLVM_BUILD_INSTRUMENTED_COVERAGE AND COMPILER_RT_HAS_FNO_COVERAGE_MAPPING_FLAG) + list(APPEND NO_PGO_FLAGS "-fno-coverage-mapping") + endif() endif() endif() @@ -228,6 +250,17 @@ function(add_compiler_rt_runtime name type) get_compiler_rt_output_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} output_dir_${libname}) get_compiler_rt_install_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} install_dir_${libname}) endif() + + # Build the macOS sanitizers with Mac Catalyst support. + if ("${COMPILER_RT_ENABLE_MACCATALYST}" AND + "${os}" MATCHES "^(osx)$") + foreach(arch ${LIB_ARCHS_${libname}}) + list(APPEND extra_cflags_${libname} + "SHELL:-target ${arch}-apple-macos${DARWIN_osx_MIN_VER} -darwin-target-variant ${arch}-apple-ios13.1-macabi") + list(APPEND extra_link_flags_${libname} + "SHELL:-target ${arch}-apple-macos${DARWIN_osx_MIN_VER} -darwin-target-variant ${arch}-apple-ios13.1-macabi") + endforeach() + endif() endforeach() else() foreach(arch ${LIB_ARCHS}) @@ -254,7 +287,7 @@ function(add_compiler_rt_runtime name type) if(COMPILER_RT_USE_BUILTINS_LIBRARY AND NOT type STREQUAL "OBJECT" AND NOT name STREQUAL "clang_rt.builtins") get_compiler_rt_target(${arch} target) - find_compiler_rt_library(builtins ${target} builtins_${libname}) + find_compiler_rt_library(builtins builtins_${libname} TARGET ${target}) if(builtins_${libname} STREQUAL "NOTFOUND") message(FATAL_ERROR "Cannot find builtins library for the target architecture") endif() @@ -359,20 +392,40 @@ function(add_compiler_rt_runtime name type) target_link_libraries(${libname} PRIVATE ${builtins_${libname}}) endif() if(${type} STREQUAL "SHARED") - if(COMMAND llvm_setup_rpath) - llvm_setup_rpath(${libname}) + if(APPLE OR WIN32) + set_property(TARGET ${libname} PROPERTY BUILD_WITH_INSTALL_RPATH ON) endif() if(WIN32 AND NOT CYGWIN AND NOT MINGW) set_target_properties(${libname} PROPERTIES IMPORT_PREFIX "") set_target_properties(${libname} PROPERTIES IMPORT_SUFFIX ".lib") endif() - if(APPLE) - # Ad-hoc sign the dylibs - add_custom_command(TARGET ${libname} - POST_BUILD - COMMAND codesign --sign - $ - WORKING_DIRECTORY ${COMPILER_RT_OUTPUT_LIBRARY_DIR} + if (APPLE AND NOT CMAKE_LINKER MATCHES ".*lld.*") + # Ad-hoc sign the dylibs when using Xcode versions older than 12. + # Xcode 12 shipped with ld64-609. + # FIXME: Remove whole conditional block once everything uses Xcode 12+. + set(LD_V_OUTPUT) + execute_process( + COMMAND sh -c "${CMAKE_LINKER} -v 2>&1 | head -1" + RESULT_VARIABLE HAD_ERROR + OUTPUT_VARIABLE LD_V_OUTPUT ) + if (HAD_ERROR) + message(FATAL_ERROR "${CMAKE_LINKER} failed with status ${HAD_ERROR}") + endif() + set(NEED_EXPLICIT_ADHOC_CODESIGN 1) + if ("${LD_V_OUTPUT}" MATCHES ".*ld64-([0-9.]+).*") + string(REGEX REPLACE ".*ld64-([0-9.]+).*" "\\1" HOST_LINK_VERSION ${LD_V_OUTPUT}) + if (HOST_LINK_VERSION VERSION_GREATER_EQUAL 609) + set(NEED_EXPLICIT_ADHOC_CODESIGN 0) + endif() + endif() + if (NEED_EXPLICIT_ADHOC_CODESIGN) + add_custom_command(TARGET ${libname} + POST_BUILD + COMMAND codesign --sign - $ + WORKING_DIRECTORY ${COMPILER_RT_OUTPUT_LIBRARY_DIR} + ) + endif() endif() endif() @@ -490,7 +543,7 @@ function(add_compiler_rt_test test_suite test_name arch) endif() add_custom_command( OUTPUT "${output_bin}" - COMMAND ${COMPILER_RT_TEST_COMPILER} ${TEST_OBJECTS} -o "${output_bin}" + COMMAND ${COMPILER_RT_TEST_CXX_COMPILER} ${TEST_OBJECTS} -o "${output_bin}" ${TEST_LINK_FLAGS} DEPENDS ${TEST_DEPS} ) @@ -559,13 +612,9 @@ macro(add_custom_libcxx name prefix) -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}) endif() - set(STAMP_DIR ${prefix}-stamps/) - set(BINARY_DIR ${prefix}-bins/) - add_custom_target(${name}-clear - COMMAND ${CMAKE_COMMAND} -E remove_directory ${BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E remove_directory ${STAMP_DIR} - COMMENT "Clobbering ${name} build and stamp directories" + COMMAND ${CMAKE_COMMAND} -E remove_directory ${prefix} + COMMENT "Clobbering ${name} build directories" USES_TERMINAL ) set_target_properties(${name}-clear PROPERTIES FOLDER "Compiler-RT Misc") @@ -573,10 +622,9 @@ macro(add_custom_libcxx name prefix) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp DEPENDS ${LIBCXX_DEPS} ${toolchain_deps} - COMMAND ${CMAKE_COMMAND} -E touch ${BINARY_DIR}/CMakeCache.txt - COMMAND ${CMAKE_COMMAND} -E touch ${STAMP_DIR}/${name}-mkdir + COMMAND ${CMAKE_COMMAND} -E touch ${prefix}/CMakeCache.txt COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp - COMMENT "Clobbering bootstrap build and stamp directories" + COMMENT "Clobbering bootstrap build directories" ) add_custom_target(${name}-clobber @@ -598,8 +646,14 @@ macro(add_custom_libcxx name prefix) CMAKE_OBJCOPY CMAKE_OBJDUMP CMAKE_STRIP + CMAKE_READELF CMAKE_SYSROOT LIBCXX_HAS_MUSL_LIBC + LIBCXX_HAS_GCC_S_LIB + LIBCXX_HAS_PTHREAD_LIB + LIBCXX_HAS_RT_LIB + LIBCXX_USE_COMPILER_RT + LIBCXXABI_HAS_PTHREAD_LIB PYTHON_EXECUTABLE Python3_EXECUTABLE Python2_EXECUTABLE @@ -622,10 +676,9 @@ macro(add_custom_libcxx name prefix) ExternalProject_Add(${name} DEPENDS ${name}-clobber ${LIBCXX_DEPS} - PREFIX ${prefix} - SOURCE_DIR ${COMPILER_RT_SOURCE_DIR}/cmake/Modules/CustomLibcxx - STAMP_DIR ${STAMP_DIR} - BINARY_DIR ${BINARY_DIR} + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/${name} + SOURCE_DIR ${LLVM_MAIN_SRC_DIR}/../runtimes + BINARY_DIR ${prefix} CMAKE_ARGS ${CMAKE_PASSTHROUGH_VARIABLES} ${compiler_args} -DCMAKE_C_FLAGS=${LIBCXX_C_FLAGS} @@ -633,10 +686,16 @@ macro(add_custom_libcxx name prefix) -DCMAKE_BUILD_TYPE=Release -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY -DLLVM_PATH=${LLVM_MAIN_SRC_DIR} - -DLLVM_BINARY_DIR=${prefix} - -DLLVM_LIBRARY_OUTPUT_INTDIR=${prefix}/lib - -DCOMPILER_RT_LIBCXX_PATH=${COMPILER_RT_LIBCXX_PATH} - -DCOMPILER_RT_LIBCXXABI_PATH=${COMPILER_RT_LIBCXXABI_PATH} + -DLLVM_ENABLE_RUNTIMES=libcxx|libcxxabi + -DLIBCXXABI_ENABLE_SHARED=OFF + -DLIBCXXABI_HERMETIC_STATIC_LIBRARY=ON + -DLIBCXXABI_INCLUDE_TESTS=OFF + -DLIBCXX_CXX_ABI=libcxxabi + -DLIBCXX_ENABLE_SHARED=OFF + -DLIBCXX_HERMETIC_STATIC_LIBRARY=ON + -DLIBCXX_INCLUDE_BENCHMARKS=OFF + -DLIBCXX_INCLUDE_TESTS=OFF + -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON ${LIBCXX_CMAKE_ARGS} INSTALL_COMMAND "" STEP_TARGETS configure build @@ -644,14 +703,15 @@ macro(add_custom_libcxx name prefix) USES_TERMINAL_CONFIGURE 1 USES_TERMINAL_BUILD 1 USES_TERMINAL_INSTALL 1 + LIST_SEPARATOR | EXCLUDE_FROM_ALL TRUE BUILD_BYPRODUCTS "${prefix}/lib/libc++.a" "${prefix}/lib/libc++abi.a" ) if (CMAKE_GENERATOR MATCHES "Make") - set(run_clean "$(MAKE)" "-C" "${BINARY_DIR}" "clean") + set(run_clean "$(MAKE)" "-C" "${prefix}" "clean") else() - set(run_clean ${CMAKE_COMMAND} --build ${BINARY_DIR} --target clean + set(run_clean ${CMAKE_COMMAND} --build ${prefix} --target clean --config "$") endif() @@ -660,7 +720,7 @@ macro(add_custom_libcxx name prefix) COMMENT "Cleaning ${name}..." DEPENDEES configure ${force_deps} - WORKING_DIRECTORY ${BINARY_DIR} + WORKING_DIRECTORY ${prefix} EXCLUDE_FROM_MAIN 1 USES_TERMINAL 1 ) diff --git a/gnu/llvm/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/gnu/llvm/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake new file mode 100644 index 00000000000..cc929c521f8 --- /dev/null +++ b/gnu/llvm/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake @@ -0,0 +1,88 @@ +set(ARM64 aarch64) +set(ARM32 arm armhf) +set(HEXAGON hexagon) +set(X86 i386) +set(X86_64 x86_64) +set(LOONGARCH64 loongarch64) +set(MIPS32 mips mipsel) +set(MIPS64 mips64 mips64el) +set(PPC32 powerpc powerpcspe) +set(PPC64 powerpc64 powerpc64le) +set(RISCV32 riscv32) +set(RISCV64 riscv64) +set(S390X s390x) +set(SPARC sparc) +set(SPARCV9 sparcv9) +set(WASM32 wasm32) +set(WASM64 wasm64) +set(VE ve) + +if(APPLE) + set(ARM64 arm64) + set(ARM32 armv7 armv7s armv7k) + set(X86_64 x86_64 x86_64h) +endif() + +set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64} ${RISCV64} + ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} + ${HEXAGON} ${LOONGARCH64}) +set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} + ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON} + ${LOONGARCH64}) +set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) + +if(ANDROID) + set(OS_NAME "Android") +else() + set(OS_NAME "${CMAKE_SYSTEM_NAME}") +endif() + +if(OS_NAME MATCHES "Linux") + set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${S390X}) +elseif (OS_NAME MATCHES "Windows") + set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64}) +elseif(OS_NAME MATCHES "Android") + set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}) +else() + set(ALL_FUZZER_SUPPORTED_ARCH ${X86_64} ${ARM64}) +endif() + +set(ALL_GWP_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}) +if(APPLE) + set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64}) +else() + set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64} ${ARM32} + ${PPC64} ${S390X} ${RISCV64} ${HEXAGON} ${LOONGARCH64}) +endif() +set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}) +set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64} ${RISCV64}) +set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64}) +set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64} + ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON} + ${RISCV32} ${RISCV64}) +set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X} + ${LOONGARCH64}) +set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} + ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON} + ${LOONGARCH64}) +set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64} + ${HEXAGON} ${LOONGARCH64}) +set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64} + ${HEXAGON}) +set(ALL_SCUDO_STANDALONE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} + ${MIPS32} ${MIPS64} ${PPC64} ${HEXAGON} ${LOONGARCH64}) +if(APPLE) +set(ALL_XRAY_SUPPORTED_ARCH ${X86_64}) +else() +set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} + powerpc64le ${HEXAGON}) +endif() +set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64}) + +if (UNIX) +set(ALL_ORC_SUPPORTED_ARCH ${X86_64} ${ARM64} ${ARM32}) +endif() + +if (WIN32) + set(ALL_ORC_SUPPORTED_ARCH ${X86_64}) +endif() diff --git a/gnu/llvm/compiler-rt/cmake/Modules/BuiltinTests.cmake b/gnu/llvm/compiler-rt/cmake/Modules/BuiltinTests.cmake index 4a123638c8b..7d71ca3f71e 100644 --- a/gnu/llvm/compiler-rt/cmake/Modules/BuiltinTests.cmake +++ b/gnu/llvm/compiler-rt/cmake/Modules/BuiltinTests.cmake @@ -46,7 +46,7 @@ function(try_compile_only output) set(TRY_COMPILE_FLAGS "${ARG_FLAGS}") if(CMAKE_C_COMPILER_ID MATCHES Clang AND CMAKE_C_COMPILER_TARGET) - list(APPEND TRY_COMPILE_FLAGS "-target ${CMAKE_C_COMPILER_TARGET}") + list(APPEND TRY_COMPILE_FLAGS "--target=${CMAKE_C_COMPILER_TARGET}") endif() string(REPLACE ";" " " extra_flags "${TRY_COMPILE_FLAGS}") @@ -74,7 +74,7 @@ function(try_compile_only output) # Strip quotes from the compile command, as the compiler is not expecting # quoted arguments (see discussion on D62063 for when this can come up). If - # the quotes were there for arugments with spaces in them, the quotes were + # the quotes were there for arguments with spaces in them, the quotes were # not going to help since the string gets split on spaces below. string(REPLACE "\"" "" test_compile_command "${test_compile_command}") diff --git a/gnu/llvm/compiler-rt/cmake/Modules/CheckSectionExists.cmake b/gnu/llvm/compiler-rt/cmake/Modules/CheckSectionExists.cmake new file mode 100644 index 00000000000..cb32276b5ae --- /dev/null +++ b/gnu/llvm/compiler-rt/cmake/Modules/CheckSectionExists.cmake @@ -0,0 +1,91 @@ +function(check_section_exists section output) + cmake_parse_arguments(ARG "" "" "SOURCE;FLAGS" ${ARGN}) + if(NOT ARG_SOURCE) + set(ARG_SOURCE "int main(void) { return 0; }\n") + endif() + + string(RANDOM TARGET_NAME) + set(TARGET_NAME "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cmTC_${TARGET_NAME}.dir") + file(MAKE_DIRECTORY ${TARGET_NAME}) + + file(WRITE "${TARGET_NAME}/CheckSectionExists.c" "${ARG_SOURCE}\n") + + string(REGEX MATCHALL "<[A-Za-z0-9_]*>" substitutions + ${CMAKE_C_COMPILE_OBJECT}) + + set(try_compile_flags "${ARG_FLAGS}") + if(CMAKE_C_COMPILER_ID MATCHES Clang AND CMAKE_C_COMPILER_TARGET) + list(APPEND try_compile_flags "-target ${CMAKE_C_COMPILER_TARGET}") + endif() + append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto try_compile_flags) + if(NOT COMPILER_RT_ENABLE_PGO) + if(LLVM_PROFDATA_FILE AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_USE_FLAG) + list(APPEND try_compile_flags "-fno-profile-instr-use") + endif() + if(LLVM_BUILD_INSTRUMENTED MATCHES IR AND COMPILER_RT_HAS_FNO_PROFILE_GENERATE_FLAG) + list(APPEND try_compile_flags "-fno-profile-generate") + elseif((LLVM_BUILD_INSTRUMENTED OR LLVM_BUILD_INSTRUMENTED_COVERAGE) AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG) + list(APPEND try_compile_flags "-fno-profile-instr-generate") + if(LLVM_BUILD_INSTRUMENTED_COVERAGE AND COMPILER_RT_HAS_FNO_COVERAGE_MAPPING_FLAG) + list(APPEND try_compile_flags "-fno-coverage-mapping") + endif() + endif() + endif() + + string(REPLACE ";" " " extra_flags "${try_compile_flags}") + + set(test_compile_command "${CMAKE_C_COMPILE_OBJECT}") + foreach(substitution ${substitutions}) + if(substitution STREQUAL "") + string(REPLACE "" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" + test_compile_command ${test_compile_command}) + elseif(substitution STREQUAL "") + string(REPLACE "" "${TARGET_NAME}/CheckSectionExists.o" + test_compile_command ${test_compile_command}) + elseif(substitution STREQUAL "") + string(REPLACE "" "${TARGET_NAME}/CheckSectionExists.c" + test_compile_command ${test_compile_command}) + elseif(substitution STREQUAL "") + string(REPLACE "" "${CMAKE_C_FLAGS} ${extra_flags}" + test_compile_command ${test_compile_command}) + else() + string(REPLACE "${substitution}" "" test_compile_command + ${test_compile_command}) + endif() + endforeach() + + # Strip quotes from the compile command, as the compiler is not expecting + # quoted arguments (potential quotes added from D62063). + string(REPLACE "\"" "" test_compile_command "${test_compile_command}") + + string(REPLACE " " ";" test_compile_command "${test_compile_command}") + + execute_process( + COMMAND ${test_compile_command} + RESULT_VARIABLE TEST_RESULT + OUTPUT_VARIABLE TEST_OUTPUT + ERROR_VARIABLE TEST_ERROR + ) + + # Explicitly throw a fatal error message if test_compile_command fails. + if(TEST_RESULT) + message(FATAL_ERROR "${TEST_ERROR}") + return() + endif() + + execute_process( + COMMAND ${CMAKE_OBJDUMP} -h "${TARGET_NAME}/CheckSectionExists.o" + RESULT_VARIABLE CHECK_RESULT + OUTPUT_VARIABLE CHECK_OUTPUT + ERROR_VARIABLE CHECK_ERROR + ) + string(FIND "${CHECK_OUTPUT}" "${section}" SECTION_FOUND) + + if(NOT SECTION_FOUND EQUAL -1) + set(${output} TRUE PARENT_SCOPE) + else() + set(${output} FALSE PARENT_SCOPE) + endif() + + file(REMOVE_RECURSE ${TARGET_NAME}) +endfunction() diff --git a/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTAIXUtils.cmake b/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTAIXUtils.cmake index 3b61430f471..d28b46463e7 100644 --- a/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTAIXUtils.cmake +++ b/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTAIXUtils.cmake @@ -2,16 +2,16 @@ include(CMakeParseArguments) include(CompilerRTUtils) function(get_aix_libatomic_default_link_flags link_flags export_list) - set(linkopts - "-Wl,-H512 -Wl,-D0 \ - -Wl,-T512 -Wl,-bhalt:4 -Wl,-bernotok \ - -Wl,-bnoentry -Wl,-bexport:${export_list} \ - -Wl,-bmodtype:SRE -Wl,-lc") +set(linkopts + -Wl,-H512 -Wl,-D0 + -Wl,-T512 -Wl,-bhalt:4 -Wl,-bernotok + -Wl,-bnoentry -Wl,-bexport:${export_list} + -Wl,-bmodtype:SRE -Wl,-lc) # Add `-Wl,-G`. Quoted from release notes of cmake-3.16.0 # > On AIX, runtime linking is no longer enabled by default. # See https://cmake.org/cmake/help/latest/release/3.16.html if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16.0") - set(linkopts "-Wl,-G" "${linkopts}") + set(linkopts -Wl,-G ${linkopts}) endif() set(${link_flags} ${linkopts} PARENT_SCOPE) endfunction() @@ -24,16 +24,16 @@ function(get_aix_libatomic_type type) endif() endfunction() -macro(archive_aix_libatomic name) +macro(archive_aix_libatomic name libname) cmake_parse_arguments(LIB "" "" "ARCHS;PARENT_TARGET" ${ARGN}) - set(shared_libraries_to_archive "") + set(objects_to_archive "") foreach (arch ${LIB_ARCHS}) if(CAN_TARGET_${arch}) - set(output_dir "${CMAKE_CURRENT_BINARY_DIR}/libatomic-${arch}.dir") + set(output_dir "${CMAKE_CURRENT_BINARY_DIR}/${libname}-${arch}.dir") # FIXME: Target name should be kept consistent with definition # in AddCompilerRT.cmake added by # add_compiler_rt_runtime( SHARED ...) @@ -50,11 +50,11 @@ macro(archive_aix_libatomic name) COMMAND ${CMAKE_STRIP} -X32_64 -E "${output_dir}/libatomic.so.1" DEPENDS ${target}) - list(APPEND shared_libraries_to_archive "${output_dir}/libatomic.so.1") + list(APPEND objects_to_archive "${output_dir}/libatomic.so.1") endif() endif() endforeach() - if(shared_libraries_to_archive) + if(objects_to_archive) set(output_dir "") set(install_dir "") # If LLVM defines top level library directory, we want to deliver @@ -67,14 +67,14 @@ macro(archive_aix_libatomic name) get_compiler_rt_output_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} output_dir) get_compiler_rt_install_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} install_dir) endif() - add_custom_command(OUTPUT "${output_dir}/libatomic.a" - COMMAND ${CMAKE_AR} -X32_64 r "${output_dir}/libatomic.a" - ${shared_libraries_to_archive} - DEPENDS ${shared_libraries_to_archive}) - install(FILES "${output_dir}/libatomic.a" + add_custom_command(OUTPUT "${output_dir}/${libname}.a" + COMMAND ${CMAKE_AR} -X32_64 r "${output_dir}/${libname}.a" + ${objects_to_archive} + DEPENDS ${objects_to_archive}) + install(FILES "${output_dir}/${libname}.a" DESTINATION ${install_dir}) - add_custom_target(aix-libatomic - DEPENDS "${output_dir}/libatomic.a") + add_custom_target(aix-${libname} + DEPENDS "${output_dir}/${libname}.a") + add_dependencies(${LIB_PARENT_TARGET} aix-${libname}) endif() - add_dependencies(${LIB_PARENT_TARGET} aix-libatomic) endmacro() diff --git a/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTCompile.cmake b/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTCompile.cmake index 1b42f24c08d..64e7acb9afd 100644 --- a/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTCompile.cmake +++ b/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTCompile.cmake @@ -106,7 +106,8 @@ function(clang_compile object_file source) -o "${object_file}" ${source_rpath} MAIN_DEPENDENCY ${source} - DEPENDS ${SOURCE_DEPS}) + DEPENDS ${SOURCE_DEPS} + COMMAND_EXPAND_LISTS) endfunction() # On Darwin, there are no system-wide C++ headers and the just-built clang is diff --git a/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake b/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake index 276fcbb9c0e..a826c513cd8 100644 --- a/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake +++ b/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake @@ -116,7 +116,7 @@ function(darwin_test_archs os valid_archs) if(NOT TEST_COMPILE_ONLY) message(STATUS "Finding valid architectures for ${os}...") set(SIMPLE_C ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/src.c) - file(WRITE ${SIMPLE_C} "#include \nint main() { printf(__FILE__); return 0; }\n") + file(WRITE ${SIMPLE_C} "#include \nint main(void) { printf(__FILE__); return 0; }\n") set(os_linker_flags) foreach(flag ${DARWIN_${os}_LINK_FLAGS}) @@ -142,6 +142,11 @@ function(darwin_test_archs os valid_archs) list(REMOVE_ITEM archs "x86_64h") endif() + if(${os} MATCHES "iossim") + message(STATUS "Disabling i386 slice for iossim") + list(REMOVE_ITEM archs "i386") + endif() + set(working_archs) foreach(arch ${archs}) @@ -189,6 +194,8 @@ function(darwin_filter_host_archs input output) if(ARM_HOST) list(REMOVE_ITEM tmp_var i386) + list(REMOVE_ITEM tmp_var x86_64) + list(REMOVE_ITEM tmp_var x86_64h) else() list(REMOVE_ITEM tmp_var arm64) list(REMOVE_ITEM tmp_var arm64e) @@ -298,6 +305,13 @@ macro(darwin_add_builtin_library name suffix) -target "${LIB_ARCH}-apple-${base_os}${DARWIN_${LIBOS}_BUILTIN_MIN_VER}-simulator") endif() + if ("${COMPILER_RT_ENABLE_MACCATALYST}" AND + "${LIB_OS}" MATCHES "^osx$") + # Build the macOS builtins with Mac Catalyst support. + list(APPEND builtin_cflags + "SHELL:-target ${LIB_ARCH}-apple-macos${DARWIN_osx_BUILTIN_MIN_VER} -darwin-target-variant ${LIB_ARCH}-apple-ios13.1-macabi") + endif() + set_target_compile_flags(${libname} ${sysroot_flag} ${DARWIN_${LIB_OS}_BUILTIN_MIN_VER_FLAG} @@ -390,12 +404,12 @@ endfunction() macro(darwin_add_builtin_libraries) set(DARWIN_EXCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Darwin-excludes) - set(CFLAGS "-fPIC -O3 -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer") + set(CFLAGS -fPIC -O3 -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer) set(CMAKE_C_FLAGS "") set(CMAKE_CXX_FLAGS "") set(CMAKE_ASM_FLAGS "") - append_string_if(COMPILER_RT_HAS_ASM_LSE " -DHAS_ASM_LSE" CFLAGS) + append_list_if(COMPILER_RT_HAS_ASM_LSE -DHAS_ASM_LSE CFLAGS) set(PROFILE_SOURCES ../profile/InstrProfiling.c ../profile/InstrProfilingBuffer.c @@ -404,6 +418,12 @@ macro(darwin_add_builtin_libraries) ../profile/InstrProfilingInternal.c ../profile/InstrProfilingVersionVar.c) foreach (os ${ARGN}) + set(macosx_sdk_version 99999) + if ("${os}" STREQUAL "osx") + find_darwin_sdk_version(macosx_sdk_version "macosx") + endif() + add_security_warnings(CFLAGS ${macosx_sdk_version}) + list_intersect(DARWIN_BUILTIN_ARCHS DARWIN_${os}_BUILTIN_ARCHS BUILTIN_SUPPORTED_ARCH) if((arm64 IN_LIST DARWIN_BUILTIN_ARCHS OR arm64e IN_LIST DARWIN_BUILTIN_ARCHS) AND NOT TARGET lse_builtin_symlinks) @@ -505,7 +525,7 @@ macro(darwin_add_embedded_builtin_libraries) set(MACHO_SYM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/macho_embedded) - set(CFLAGS "-Oz -Wall -fomit-frame-pointer -ffreestanding") + set(CFLAGS -Oz -Wall -fomit-frame-pointer -ffreestanding) set(CMAKE_C_FLAGS "") set(CMAKE_CXX_FLAGS "") set(CMAKE_ASM_FLAGS "") @@ -524,8 +544,8 @@ macro(darwin_add_embedded_builtin_libraries) set(DARWIN_macho_embedded_LIBRARY_INSTALL_DIR ${COMPILER_RT_INSTALL_LIBRARY_DIR}/macho_embedded) - set(CFLAGS_armv7 "-target thumbv7-apple-darwin-eabi") - set(CFLAGS_i386 "-march=pentium") + 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) diff --git a/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTMockLLVMCMakeConfig.cmake b/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTMockLLVMCMakeConfig.cmake index 1080a4d0a79..4b71369642a 100644 --- a/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTMockLLVMCMakeConfig.cmake +++ b/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTMockLLVMCMakeConfig.cmake @@ -13,20 +13,20 @@ macro(compiler_rt_mock_llvm_cmake_config) endmacro() macro(compiler_rt_mock_llvm_cmake_config_set_cmake_path) - # Point `LLVM_CMAKE_PATH` at the source tree in the monorepo. - set(LLVM_CMAKE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules") - if (NOT EXISTS "${LLVM_CMAKE_PATH}") - message(FATAL_ERROR "LLVM_CMAKE_PATH (${LLVM_CMAKE_PATH}) does not exist") + # Point `LLVM_CMAKE_DIR` at the source tree in the monorepo. + set(LLVM_CMAKE_DIR "${LLVM_MAIN_SRC_DIR}/cmake/modules") + if (NOT EXISTS "${LLVM_CMAKE_DIR}") + message(FATAL_ERROR "LLVM_CMAKE_DIR (${LLVM_CMAKE_DIR}) does not exist") endif() - list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") - message(STATUS "LLVM_CMAKE_PATH: \"${LLVM_CMAKE_PATH}\"") + list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") + message(STATUS "LLVM_CMAKE_DIR: \"${LLVM_CMAKE_DIR}\"") endmacro() function(compiler_rt_mock_llvm_cmake_config_set_target_triple) - # Various bits of compiler-rt depend on the `TARGET_TRIPLE`variable being - # defined. This function tries to set a sensible value for the variable. - # This is a function rather than a macro to avoid polluting the variable - # namespace. + # Various bits of compiler-rt depend on the `LLVM_TARGET_TRIPLE` variable + # being defined. This function tries to set a sensible value for the + # variable. This is a function rather than a macro to avoid polluting the + # variable namespace. set(COMPILER_OUTPUT "") # If the user provides `COMPILER_RT_DEFAULT_TARGET_ONLY` and `CMAKE_C_COMPILER_TARGET` @@ -35,7 +35,7 @@ function(compiler_rt_mock_llvm_cmake_config_set_target_triple) if (COMPILER_RT_DEFAULT_TARGET_ONLY) if (NOT "${CMAKE_C_COMPILER_TARGET}" STREQUAL "") message(STATUS - "Using CMAKE_C_COMPILER_TARGET (${CMAKE_C_COMPILER_TARGET}) as TARGET_TRIPLE") + "Using CMAKE_C_COMPILER_TARGET (${CMAKE_C_COMPILER_TARGET}) as LLVM_TARGET_TRIPLE") endif() set(COMPILER_OUTPUT "${CMAKE_C_COMPILER_TARGET}") endif() @@ -61,15 +61,15 @@ function(compiler_rt_mock_llvm_cmake_config_set_target_triple) if (HAD_ERROR) message(FATAL_ERROR "Fetching target triple from compiler failed") endif() - set(TARGET_TRIPLE "${COMPILER_OUTPUT}") - message(STATUS "TARGET_TRIPLE: \"${TARGET_TRIPLE}\"") - if ("${TARGET_TRIPLE}" STREQUAL "") + set(LLVM_TARGET_TRIPLE "${COMPILER_OUTPUT}") + message(STATUS "TARGET_TRIPLE: \"${LLVM_TARGET_TRIPLE}\"") + if ("${LLVM_TARGET_TRIPLE}" STREQUAL "") message(FATAL_ERROR "TARGET_TRIPLE cannot be empty") endif() - set(TARGET_TRIPLE "${TARGET_TRIPLE}" PARENT_SCOPE) + set(LLVM_TARGET_TRIPLE "${LLVM_TARGET_TRIPLE}" PARENT_SCOPE) endfunction() macro(compiler_rt_mock_llvm_cmake_config_include_cmake_files) # Some compiler-rt CMake code needs to call code in this file. - include("${LLVM_CMAKE_PATH}/AddLLVM.cmake") + include("${LLVM_CMAKE_DIR}/AddLLVM.cmake") endmacro() diff --git a/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTUtils.cmake index 5543e3c6afc..eefc466a461 100644 --- a/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTUtils.cmake +++ b/gnu/llvm/compiler-rt/cmake/Modules/CompilerRTUtils.cmake @@ -5,19 +5,11 @@ include(CheckSymbolExists) # define a handy helper function for it. The compile flags setting in CMake # has serious issues that make its syntax challenging at best. function(set_target_compile_flags target) - set(argstring "") - foreach(arg ${ARGN}) - set(argstring "${argstring} ${arg}") - endforeach() - set_property(TARGET ${target} PROPERTY COMPILE_FLAGS "${argstring}") + set_property(TARGET ${target} PROPERTY COMPILE_OPTIONS ${ARGN}) endfunction() function(set_target_link_flags target) - set(argstring "") - foreach(arg ${ARGN}) - set(argstring "${argstring} ${arg}") - endforeach() - set_property(TARGET ${target} PROPERTY LINK_FLAGS "${argstring}") + set_property(TARGET ${target} PROPERTY LINK_OPTIONS ${ARGN}) endfunction() # Set the variable var_PYBOOL to True if var holds a true-ish string, @@ -128,7 +120,9 @@ macro(test_target_arch arch def) if(NOT HAS_${arch}_DEF) set(CAN_TARGET_${arch} FALSE) elseif(TEST_COMPILE_ONLY) - try_compile_only(CAN_TARGET_${arch} FLAGS ${TARGET_${arch}_CFLAGS}) + try_compile_only(CAN_TARGET_${arch} + SOURCE "#include \nint foo(int x, int y) { return x + y; }\n" + FLAGS ${TARGET_${arch}_CFLAGS}) else() set(FLAG_NO_EXCEPTIONS "") if(COMPILER_RT_HAS_FNO_EXCEPTIONS_FLAG) @@ -153,9 +147,11 @@ endmacro() macro(detect_target_arch) check_symbol_exists(__arm__ "" __ARM) + check_symbol_exists(__AVR__ "" __AVR) check_symbol_exists(__aarch64__ "" __AARCH64) check_symbol_exists(__x86_64__ "" __X86_64) check_symbol_exists(__i386__ "" __I386) + check_symbol_exists(__loongarch__ "" __LOONGARCH) check_symbol_exists(__mips__ "" __MIPS) check_symbol_exists(__mips64__ "" __MIPS64) check_symbol_exists(__powerpc__ "" __PPC) @@ -170,6 +166,8 @@ macro(detect_target_arch) check_symbol_exists(__ve__ "" __VE) if(__ARM) add_default_target_arch(arm) + elseif(__AVR) + add_default_target_arch(avr) elseif(__AARCH64) add_default_target_arch(aarch64) elseif(__X86_64) @@ -182,6 +180,14 @@ macro(detect_target_arch) endif() elseif(__I386) add_default_target_arch(i386) + elseif(__LOONGARCH) + if(CMAKE_SIZEOF_VOID_P EQUAL "4") + add_default_target_arch(loongarch32) + elseif(CMAKE_SIZEOF_VOID_P EQUAL "8") + add_default_target_arch(loongarch64) + else() + message(FATAL_ERROR "Unsupported pointer size for LoongArch") + endif() elseif(__MIPS64) # must be checked before __MIPS add_default_target_arch(mips64) elseif(__MIPS) @@ -238,6 +244,10 @@ function(get_compiler_rt_root_source_dir ROOT_DIR_VAR) # Compiler-RT Builtins standalone build. # `llvm-project/compiler-rt/lib/builtins` set(PATH_TO_COMPILER_RT_SOURCE_ROOT "${CompilerRTBuiltins_SOURCE_DIR}/../../") + elseif (DEFINED CompilerRTCRT_SOURCE_DIR) + # Compiler-RT CRT standalone build. + # `llvm-project/compiler-rt/lib/crt` + set(PATH_TO_COMPILER_RT_SOURCE_ROOT "${CompilerRTCRT_SOURCE_DIR}/../../") elseif(DEFINED CompilerRT_SOURCE_DIR) # Compiler-RT standalone build. # `llvm-project/compiler-rt` @@ -267,14 +277,15 @@ function(get_compiler_rt_root_source_dir ROOT_DIR_VAR) endfunction() macro(load_llvm_config) - if (NOT LLVM_CONFIG_PATH) - find_program(LLVM_CONFIG_PATH "llvm-config" - DOC "Path to llvm-config binary") - if (NOT LLVM_CONFIG_PATH) - message(WARNING "UNSUPPORTED COMPILER-RT CONFIGURATION DETECTED: " - "llvm-config not found.\n" - "Reconfigure with -DLLVM_CONFIG_PATH=path/to/llvm-config.") - endif() + if (LLVM_CONFIG_PATH AND NOT LLVM_CMAKE_DIR) + message(WARNING + "LLVM_CONFIG_PATH is deprecated, please use LLVM_CMAKE_DIR instead") + # Compute the path to the LLVM install prefix and pass it as LLVM_CMAKE_DIR, + # CMake will locate the appropriate lib*/cmake subdirectory from there. + # For example. for -DLLVM_CONFIG_PATH=/usr/lib/llvm/16/bin/llvm-config + # this will yield LLVM_CMAKE_DIR=/usr/lib/llvm/16. + get_filename_component(LLVM_CMAKE_DIR "${LLVM_CONFIG_PATH}" DIRECTORY) + get_filename_component(LLVM_CMAKE_DIR "${LLVM_CMAKE_DIR}" DIRECTORY) endif() # Compute path to LLVM sources assuming the monorepo layout. @@ -289,114 +300,37 @@ macro(load_llvm_config) "You are not using the monorepo layout. This configuration is DEPRECATED.") endif() - set(FOUND_LLVM_CMAKE_PATH FALSE) - if (LLVM_CONFIG_PATH) - execute_process( - COMMAND ${LLVM_CONFIG_PATH} "--obj-root" "--bindir" "--libdir" "--src-root" "--includedir" - RESULT_VARIABLE HAD_ERROR - OUTPUT_VARIABLE CONFIG_OUTPUT) - if (HAD_ERROR) - message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}") - endif() - string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT}) - list(GET CONFIG_OUTPUT 0 BINARY_DIR) - list(GET CONFIG_OUTPUT 1 TOOLS_BINARY_DIR) - list(GET CONFIG_OUTPUT 2 LIBRARY_DIR) - list(GET CONFIG_OUTPUT 3 MAIN_SRC_DIR) - list(GET CONFIG_OUTPUT 4 INCLUDE_DIR) - - set(LLVM_BINARY_DIR ${BINARY_DIR} CACHE PATH "Path to LLVM build tree") - set(LLVM_LIBRARY_DIR ${LIBRARY_DIR} CACHE PATH "Path to llvm/lib") - set(LLVM_TOOLS_BINARY_DIR ${TOOLS_BINARY_DIR} CACHE PATH "Path to llvm/bin") - set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Paths to LLVM headers") - - if (NOT EXISTS "${LLVM_MAIN_SRC_DIR_DEFAULT}") - # TODO(dliew): Remove this legacy fallback path. - message(WARNING - "Consulting llvm-config for the LLVM source path " - "as a fallback. This behavior will be removed in the future.") - # We don't set `LLVM_MAIN_SRC_DIR` directly to avoid overriding a user - # provided CMake cache value. - set(LLVM_MAIN_SRC_DIR_DEFAULT "${MAIN_SRC_DIR}") - message(STATUS "Using LLVM source path (${LLVM_MAIN_SRC_DIR_DEFAULT}) from llvm-config") - endif() - - # Detect if we have the LLVMXRay and TestingSupport library installed and - # available from llvm-config. - execute_process( - COMMAND ${LLVM_CONFIG_PATH} "--ldflags" "--libs" "xray" - RESULT_VARIABLE HAD_ERROR - OUTPUT_VARIABLE CONFIG_OUTPUT - ERROR_QUIET) - if (HAD_ERROR) - message(WARNING "llvm-config finding xray failed with status ${HAD_ERROR}") + find_package(LLVM HINTS "${LLVM_CMAKE_DIR}") + if (NOT LLVM_FOUND) + message(WARNING "UNSUPPORTED COMPILER-RT CONFIGURATION DETECTED: " + "LLVM cmake package not found.\n" + "Reconfigure with -DLLVM_CMAKE_DIR=/path/to/llvm.") + else() + list(APPEND CMAKE_MODULE_PATH "${LLVM_DIR}") + # Turn into CACHE PATHs for overwritting + set(LLVM_BINARY_DIR "${LLVM_BINARY_DIR}" CACHE PATH "Path to LLVM build tree") + set(LLVM_LIBRARY_DIR "${LLVM_LIBRARY_DIR}" CACHE PATH "Path to llvm/lib") + set(LLVM_TOOLS_BINARY_DIR "${LLVM_TOOLS_BINARY_DIR}" CACHE PATH "Path to llvm/bin") + set(LLVM_INCLUDE_DIR ${LLVM_INCLUDE_DIRS} CACHE PATH "Path to llvm/include and any other header dirs needed") + + list(FIND LLVM_AVAILABLE_LIBS LLVMXRay XRAY_INDEX) + set(COMPILER_RT_HAS_LLVMXRAY TRUE) + if (XRAY_INDEX EQUAL -1) + message(WARNING "LLVMXRay not found in LLVM_AVAILABLE_LIBS") set(COMPILER_RT_HAS_LLVMXRAY FALSE) - else() - string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT}) - list(GET CONFIG_OUTPUT 0 LDFLAGS) - list(GET CONFIG_OUTPUT 1 LIBLIST) - file(TO_CMAKE_PATH "${LDFLAGS}" LDFLAGS) - file(TO_CMAKE_PATH "${LIBLIST}" LIBLIST) - set(LLVM_XRAY_LDFLAGS ${LDFLAGS} CACHE STRING "Linker flags for LLVMXRay library") - set(LLVM_XRAY_LIBLIST ${LIBLIST} CACHE STRING "Library list for LLVMXRay") - set(COMPILER_RT_HAS_LLVMXRAY TRUE) endif() - set(COMPILER_RT_HAS_LLVMTESTINGSUPPORT FALSE) - execute_process( - COMMAND ${LLVM_CONFIG_PATH} "--ldflags" "--libs" "testingsupport" - RESULT_VARIABLE HAD_ERROR - OUTPUT_VARIABLE CONFIG_OUTPUT - ERROR_QUIET) - if (HAD_ERROR) - message(WARNING "llvm-config finding testingsupport failed with status ${HAD_ERROR}") - elseif(COMPILER_RT_INCLUDE_TESTS) - string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT}) - list(GET CONFIG_OUTPUT 0 LDFLAGS) - list(GET CONFIG_OUTPUT 1 LIBLIST) - if (LIBLIST STREQUAL "") - message(WARNING "testingsupport library not installed, some tests will be skipped") - else() - file(TO_CMAKE_PATH "${LDFLAGS}" LDFLAGS) - file(TO_CMAKE_PATH "${LIBLIST}" LIBLIST) - set(LLVM_TESTINGSUPPORT_LDFLAGS ${LDFLAGS} CACHE STRING "Linker flags for LLVMTestingSupport library") - set(LLVM_TESTINGSUPPORT_LIBLIST ${LIBLIST} CACHE STRING "Library list for LLVMTestingSupport") - set(COMPILER_RT_HAS_LLVMTESTINGSUPPORT TRUE) - endif() - endif() - - # Make use of LLVM CMake modules. - # --cmakedir is supported since llvm r291218 (4.0 release) - execute_process( - COMMAND ${LLVM_CONFIG_PATH} --cmakedir - RESULT_VARIABLE HAD_ERROR - OUTPUT_VARIABLE CONFIG_OUTPUT) - if(NOT HAD_ERROR) - string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH_FROM_LLVM_CONFIG) - file(TO_CMAKE_PATH ${LLVM_CMAKE_PATH_FROM_LLVM_CONFIG} LLVM_CMAKE_PATH) - else() - file(TO_CMAKE_PATH ${LLVM_BINARY_DIR} LLVM_BINARY_DIR_CMAKE_STYLE) - set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm") - endif() - - set(LLVM_CMAKE_INCLUDE_FILE "${LLVM_CMAKE_PATH}/LLVMConfig.cmake") - if (EXISTS "${LLVM_CMAKE_INCLUDE_FILE}") - list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") - # Get some LLVM variables from LLVMConfig. - include("${LLVM_CMAKE_INCLUDE_FILE}") - set(FOUND_LLVM_CMAKE_PATH TRUE) - else() - set(FOUND_LLVM_CMAKE_PATH FALSE) - message(WARNING "LLVM CMake path (${LLVM_CMAKE_INCLUDE_FILE}) reported by llvm-config does not exist") + list(FIND LLVM_AVAILABLE_LIBS LLVMTestingSupport TESTINGSUPPORT_INDEX) + set(COMPILER_RT_HAS_LLVMTESTINGSUPPORT TRUE) + if (TESTINGSUPPORT_INDEX EQUAL -1) + message(WARNING "LLVMTestingSupport not found in LLVM_AVAILABLE_LIBS") + set(COMPILER_RT_HAS_LLVMTESTINGSUPPORT FALSE) endif() - unset(LLVM_CMAKE_INCLUDE_FILE) - - set(LLVM_LIBRARY_OUTPUT_INTDIR - ${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) endif() - # Finally set the cache variable now that `llvm-config` has also had a chance - # to set `LLVM_MAIN_SRC_DIR_DEFAULT`. + set(LLVM_LIBRARY_OUTPUT_INTDIR + ${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) + set(LLVM_MAIN_SRC_DIR "${LLVM_MAIN_SRC_DIR_DEFAULT}" CACHE PATH "Path to LLVM source tree") message(STATUS "LLVM_MAIN_SRC_DIR: \"${LLVM_MAIN_SRC_DIR}\"") if (NOT EXISTS "${LLVM_MAIN_SRC_DIR}") @@ -409,7 +343,7 @@ macro(load_llvm_config) "This will be treated as error in the future.") endif() - if (NOT FOUND_LLVM_CMAKE_PATH) + if (NOT LLVM_FOUND) # This configuration tries to configure without the prescence of `LLVMConfig.cmake`. It is # intended for testing purposes (generating the lit test suites) and will likely not support # a build of the runtimes in compiler-rt. @@ -426,18 +360,12 @@ macro(construct_compiler_rt_default_triple) endif() set(COMPILER_RT_DEFAULT_TARGET_TRIPLE ${CMAKE_C_COMPILER_TARGET}) else() - set(COMPILER_RT_DEFAULT_TARGET_TRIPLE ${TARGET_TRIPLE} CACHE STRING + set(COMPILER_RT_DEFAULT_TARGET_TRIPLE ${LLVM_TARGET_TRIPLE} CACHE STRING "Default triple for which compiler-rt runtimes will be built.") endif() - if(DEFINED COMPILER_RT_TEST_TARGET_TRIPLE) - # Backwards compatibility: this variable used to be called - # COMPILER_RT_TEST_TARGET_TRIPLE. - set(COMPILER_RT_DEFAULT_TARGET_TRIPLE ${COMPILER_RT_TEST_TARGET_TRIPLE}) - endif() - - string(REPLACE "-" ";" TARGET_TRIPLE_LIST ${COMPILER_RT_DEFAULT_TARGET_TRIPLE}) - list(GET TARGET_TRIPLE_LIST 0 COMPILER_RT_DEFAULT_TARGET_ARCH) + string(REPLACE "-" ";" LLVM_TARGET_TRIPLE_LIST ${COMPILER_RT_DEFAULT_TARGET_TRIPLE}) + list(GET LLVM_TARGET_TRIPLE_LIST 0 COMPILER_RT_DEFAULT_TARGET_ARCH) # Map various forms of the architecture names to the canonical forms # (as they are used by clang, see getArchNameForCompilerRTLib). @@ -448,7 +376,7 @@ macro(construct_compiler_rt_default_triple) # Determine if test target triple is specified explicitly, and doesn't match the # default. - if(NOT COMPILER_RT_DEFAULT_TARGET_TRIPLE STREQUAL TARGET_TRIPLE) + if(NOT COMPILER_RT_DEFAULT_TARGET_TRIPLE STREQUAL LLVM_TARGET_TRIPLE) set(COMPILER_RT_HAS_EXPLICIT_DEFAULT_TARGET_TRIPLE TRUE) else() set(COMPILER_RT_HAS_EXPLICIT_DEFAULT_TARGET_TRIPLE FALSE) @@ -484,11 +412,46 @@ endfunction() function(get_compiler_rt_target arch variable) string(FIND ${COMPILER_RT_DEFAULT_TARGET_TRIPLE} "-" dash_index) string(SUBSTRING ${COMPILER_RT_DEFAULT_TARGET_TRIPLE} ${dash_index} -1 triple_suffix) + string(SUBSTRING ${COMPILER_RT_DEFAULT_TARGET_TRIPLE} 0 ${dash_index} triple_cpu) if(COMPILER_RT_DEFAULT_TARGET_ONLY) # Use exact spelling when building only for the target specified to CMake. set(target "${COMPILER_RT_DEFAULT_TARGET_TRIPLE}") elseif(ANDROID AND ${arch} STREQUAL "i386") set(target "i686${triple_suffix}") + elseif(${arch} STREQUAL "amd64") + set(target "x86_64${triple_suffix}") + elseif(${arch} STREQUAL "sparc64") + set(target "sparcv9${triple_suffix}") + elseif("${arch}" MATCHES "mips64|mips64el") + string(REGEX REPLACE "-gnu.*" "-gnuabi64" triple_suffix_gnu "${triple_suffix}") + string(REGEX REPLACE "mipsisa32" "mipsisa64" triple_cpu_mips "${triple_cpu}") + string(REGEX REPLACE "^mips$" "mips64" triple_cpu_mips "${triple_cpu_mips}") + string(REGEX REPLACE "^mipsel$" "mips64el" triple_cpu_mips "${triple_cpu_mips}") + set(target "${triple_cpu_mips}${triple_suffix_gnu}") + elseif("${arch}" MATCHES "mips|mipsel") + string(REGEX REPLACE "-gnuabi.*" "-gnu" triple_suffix_gnu "${triple_suffix}") + string(REGEX REPLACE "mipsisa64" "mipsisa32" triple_cpu_mips "${triple_cpu}") + string(REGEX REPLACE "mips64" "mips" triple_cpu_mips "${triple_cpu_mips}") + set(target "${triple_cpu_mips}${triple_suffix_gnu}") + elseif("${arch}" MATCHES "^arm") + # Arch is arm, armhf, armv6m (anything else would come from using + # COMPILER_RT_DEFAULT_TARGET_ONLY, which is checked above). + if (${arch} STREQUAL "armhf") + # If we are building for hard float but our ABI is soft float. + if ("${triple_suffix}" MATCHES ".*eabi$") + # Change "eabi" -> "eabihf" + set(triple_suffix "${triple_suffix}hf") + endif() + # ABI is already set in the triple, don't repeat it in the architecture. + set(arch "arm") + else () + # If we are building for soft float, but the triple's ABI is hard float. + if ("${triple_suffix}" MATCHES ".*eabihf$") + # Change "eabihf" -> "eabi" + string(REGEX REPLACE "hf$" "" triple_suffix "${triple_suffix}") + endif() + endif() + set(target "${arch}${triple_suffix}") else() set(target "${arch}${triple_suffix}") endif() @@ -598,3 +561,34 @@ function(add_compiler_rt_install_targets name) endif() endif() endfunction() + +# Add warnings to catch potential errors that can lead to security +# vulnerabilities. +function(add_security_warnings out_flags macosx_sdk_version) + set(flags "${${out_flags}}") + + append_list_if(COMPILER_RT_HAS_ARRAY_BOUNDS_FLAG -Werror=array-bounds flags) + append_list_if(COMPILER_RT_HAS_UNINITIALIZED_FLAG -Werror=uninitialized flags) + append_list_if(COMPILER_RT_HAS_SHADOW_FLAG -Werror=shadow flags) + append_list_if(COMPILER_RT_HAS_EMPTY_BODY_FLAG -Werror=empty-body flags) + append_list_if(COMPILER_RT_HAS_SIZEOF_POINTER_MEMACCESS_FLAG -Werror=sizeof-pointer-memaccess flags) + append_list_if(COMPILER_RT_HAS_SIZEOF_ARRAY_ARGUMENT_FLAG -Werror=sizeof-array-argument flags) + append_list_if(COMPILER_RT_HAS_SUSPICIOUS_MEMACCESS_FLAG -Werror=suspicious-memaccess flags) + append_list_if(COMPILER_RT_HAS_BUILTIN_MEMCPY_CHK_SIZE_FLAG -Werror=builtin-memcpy-chk-size flags) + append_list_if(COMPILER_RT_HAS_ARRAY_BOUNDS_POINTER_ARITHMETIC_FLAG -Werror=array-bounds-pointer-arithmetic flags) + append_list_if(COMPILER_RT_HAS_RETURN_STACK_ADDRESS_FLAG -Werror=return-stack-address flags) + append_list_if(COMPILER_RT_HAS_SIZEOF_ARRAY_DECAY_FLAG -Werror=sizeof-array-decay flags) + append_list_if(COMPILER_RT_HAS_FORMAT_INSUFFICIENT_ARGS_FLAG -Werror=format-insufficient-args flags) + append_list_if(COMPILER_RT_HAS_BUILTIN_FORMAL_SECURITY_FLAG -Werror=format-security flags) + append_list_if(COMPILER_RT_HAS_SIZEOF_ARRAY_DIV_FLAG -Werror=sizeof-array-div) + append_list_if(COMPILER_RT_HAS_SIZEOF_POINTER_DIV_FLAG -Werror=sizeof-pointer-div) + + # Add -Wformat-nonliteral only if we can avoid adding the definition of + # eprintf. On Apple platforms, eprintf is needed only on macosx and only if + # its version is older than 10.7. + if ("${macosx_sdk_version}" VERSION_GREATER_EQUAL 10.7) + list(APPEND flags -Werror=format-nonliteral -DDONT_DEFINE_EPRINTF) + endif() + + set(${out_flags} "${flags}" PARENT_SCOPE) +endfunction() diff --git a/gnu/llvm/compiler-rt/cmake/Modules/SanitizerUtils.cmake b/gnu/llvm/compiler-rt/cmake/Modules/SanitizerUtils.cmake index 6c8651df3b3..dea4d9a218d 100644 --- a/gnu/llvm/compiler-rt/cmake/Modules/SanitizerUtils.cmake +++ b/gnu/llvm/compiler-rt/cmake/Modules/SanitizerUtils.cmake @@ -3,9 +3,6 @@ include(CompilerRTUtils) set(SANITIZER_GEN_DYNAMIC_LIST ${COMPILER_RT_SOURCE_DIR}/lib/sanitizer_common/scripts/gen_dynamic_list.py) -set(SANITIZER_LINT_SCRIPT - ${COMPILER_RT_SOURCE_DIR}/lib/sanitizer_common/scripts/check_lint.sh) - if(CMAKE_NM) set(SANITIZER_NM "${CMAKE_NM}") else() @@ -95,20 +92,3 @@ macro(add_sanitizer_rt_version_list name) add_custom_target(${name}-version-list ALL DEPENDS ${vers}) endmacro() - -# Add target to check code style for sanitizer runtimes. -if(CMAKE_HOST_UNIX AND NOT OS_NAME MATCHES "OpenBSD") - add_custom_target(SanitizerLintCheck - COMMAND env LLVM_CHECKOUT=${LLVM_MAIN_SRC_DIR} SILENT=1 TMPDIR= - PYTHON_EXECUTABLE=${Python3_EXECUTABLE} - COMPILER_RT=${COMPILER_RT_SOURCE_DIR} - ${SANITIZER_LINT_SCRIPT} - DEPENDS ${SANITIZER_LINT_SCRIPT} - COMMENT "Running lint check for sanitizer sources..." - VERBATIM) -else() - add_custom_target(SanitizerLintCheck - COMMAND echo "No lint check") -endif() -set_target_properties(SanitizerLintCheck - PROPERTIES FOLDER "Compiler-RT Misc") diff --git a/gnu/llvm/compiler-rt/cmake/base-config-ix.cmake b/gnu/llvm/compiler-rt/cmake/base-config-ix.cmake index c11342e6881..c6e95055b00 100644 --- a/gnu/llvm/compiler-rt/cmake/base-config-ix.cmake +++ b/gnu/llvm/compiler-rt/cmake/base-config-ix.cmake @@ -3,8 +3,12 @@ # .o files. This is particularly useful in producing larger, more complex # runtime libraries. +include(BuiltinTests) include(CheckIncludeFile) include(CheckCXXSourceCompiles) +include(GNUInstallDirs) +include(ExtendPath) +include(CompilerRTDarwinUtils) check_include_file(unwind.h HAVE_UNWIND_H) @@ -35,14 +39,14 @@ endif() if (LLVM_TREE_AVAILABLE) # Compute the Clang version from the LLVM version. - # FIXME: We should be able to reuse CLANG_VERSION variable calculated + # FIXME: We should be able to reuse CLANG_VERSION_MAJOR variable calculated # in Clang cmake files, instead of copying the rules here. - string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION + string(REGEX MATCH "^[0-9]+" CLANG_VERSION_MAJOR ${PACKAGE_VERSION}) # Setup the paths where compiler-rt runtimes and headers should be stored. - set(COMPILER_RT_OUTPUT_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}) + set(COMPILER_RT_OUTPUT_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION_MAJOR}) set(COMPILER_RT_EXEC_OUTPUT_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR}) - set(COMPILER_RT_INSTALL_PATH lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}) + set(COMPILER_RT_INSTALL_PATH lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION_MAJOR}) option(COMPILER_RT_INCLUDE_TESTS "Generate and build compiler-rt unit tests." ${LLVM_INCLUDE_TESTS}) option(COMPILER_RT_ENABLE_WERROR "Fail and stop if warning is triggered" @@ -85,43 +89,35 @@ else() set(COMPILER_RT_TEST_COMPILER_ID GNU) endif() -function(extend_install_path joined_path current_segment) - if("${current_segment}" STREQUAL "") - set(temp_path "${COMPILER_RT_INSTALL_PATH}") - elseif("${COMPILER_RT_INSTALL_PATH}" STREQUAL "") - set(temp_path "${current_segment}") - elseif(IS_ABSOLUTE "${current_segment}") - message(WARNING "Since \"${current_segment}\" is absolute, it overrides COMPILER_RT_INSTALL_PATH: \"${COMPILER_RT_INSTALL_PATH}\".") - set(temp_path "${current_segment}") +if(NOT DEFINED COMPILER_RT_OS_DIR) + if(ANDROID) + # The CMAKE_SYSTEM_NAME for Android is Android, but the OS is Linux and the + # driver will search for compiler-rt libraries in the "linux" directory. + set(COMPILER_RT_OS_DIR linux) else() - set(temp_path "${COMPILER_RT_INSTALL_PATH}/${current_segment}") + string(TOLOWER ${CMAKE_SYSTEM_NAME} COMPILER_RT_OS_DIR) endif() - set(${joined_path} "${temp_path}" PARENT_SCOPE) -endfunction() - -if(NOT DEFINED COMPILER_RT_OS_DIR) - string(TOLOWER ${CMAKE_SYSTEM_NAME} COMPILER_RT_OS_DIR) endif() if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) set(COMPILER_RT_OUTPUT_LIBRARY_DIR ${COMPILER_RT_OUTPUT_DIR}/lib) - extend_install_path(default_install_path lib) + extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" lib) set(COMPILER_RT_INSTALL_LIBRARY_DIR "${default_install_path}" CACHE PATH "Path where built compiler-rt libraries should be installed.") else(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) set(COMPILER_RT_OUTPUT_LIBRARY_DIR ${COMPILER_RT_OUTPUT_DIR}/lib/${COMPILER_RT_OS_DIR}) - extend_install_path(default_install_path "lib/${COMPILER_RT_OS_DIR}") + extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" "lib/${COMPILER_RT_OS_DIR}") set(COMPILER_RT_INSTALL_LIBRARY_DIR "${default_install_path}" CACHE PATH "Path where built compiler-rt libraries should be installed.") endif() -extend_install_path(default_install_path bin) +extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" "${CMAKE_INSTALL_BINDIR}") set(COMPILER_RT_INSTALL_BINARY_DIR "${default_install_path}" CACHE PATH "Path where built compiler-rt executables should be installed.") -extend_install_path(default_install_path include) +extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" "${CMAKE_INSTALL_INCLUDEDIR}") set(COMPILER_RT_INSTALL_INCLUDE_DIR "${default_install_path}" CACHE PATH "Path where compiler-rt headers should be installed.") -extend_install_path(default_install_path share) +extend_path(default_install_path "${COMPILER_RT_INSTALL_PATH}" "${CMAKE_INSTALL_DATADIR}") set(COMPILER_RT_INSTALL_DATA_DIR "${default_install_path}" CACHE PATH "Path where compiler-rt data files should be installed.") @@ -144,7 +140,24 @@ if(APPLE) set(OSX_SYSROOT_FLAG "") endif() - option(COMPILER_RT_ENABLE_IOS "Enable building for iOS" On) + try_compile_only(COMPILER_RT_HAS_DARWIN_TARGET_VARIANT_FLAG + FLAGS + "-target" "x86_64-apple-macos10.15" + "-darwin-target-variant" "x86_64-apple-ios13.1-macabi" + "-Werror") + option(COMPILER_RT_ENABLE_MACCATALYST "Enable building for Mac Catalyst" ${COMPILER_RT_HAS_DARWIN_TARGET_VARIANT_FLAG}) + + # Don't enable COMPILER_RT_ENABLE_IOS if we can't find the sdk dir. + # This can happen when you only have the commandline tools installed + # which doesn't come with the iOS SDK. + find_darwin_sdk_dir(HAS_IOS_SDK "iphoneos") + set(COMPILER_RT_ENABLE_IOS_DEFAULT On) + if("${HAS_IOS_SDK}" STREQUAL "") + message(WARNING "iOS SDK not found! Building compiler-rt without iOS support.") + set(COMPILER_RT_ENABLE_IOS_DEFAULT Off) + endif() + option(COMPILER_RT_ENABLE_IOS "Enable building for iOS" ${COMPILER_RT_ENABLE_IOS_DEFAULT}) + option(COMPILER_RT_ENABLE_WATCHOS "Enable building for watchOS - Experimental" Off) option(COMPILER_RT_ENABLE_TVOS "Enable building for tvOS - Experimental" Off) @@ -204,37 +217,44 @@ macro(test_targets) test_target_arch(x86_64 "" "") endif() endif() - elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "powerpc64le") + elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "loongarch64") + test_target_arch(loongarch64 "" "") + elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "powerpc64le|ppc64le") test_target_arch(powerpc64le "" "-m64") elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "powerpc") - if(CMAKE_SYSTEM_NAME MATCHES "AIX") - test_target_arch(powerpc "" "-m32") - endif() + test_target_arch(powerpc "" "-m32") test_target_arch(powerpc64 "" "-m64") elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "s390x") test_target_arch(s390x "" "") elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "sparc") test_target_arch(sparc "" "-m32") test_target_arch(sparcv9 "" "-m64") - elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "mipsel|mips64el") - # Gcc doesn't accept -m32/-m64 so we do the next best thing and use - # -mips32r2/-mips64r2. We don't use -mips1/-mips3 because we want to match - # clang's default CPU's. In the 64-bit case, we must also specify the ABI - # since the default ABI differs between gcc and clang. - # FIXME: Ideally, we would build the N32 library too. - test_target_arch(mipsel "" "-mips32r2" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64") - test_target_arch(mips64el "" "-mips64r2" "-mabi=64") elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "mips") - test_target_arch(mips "" "-mips32r2" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64") - test_target_arch(mips64 "" "-mips64r2" "-mabi=64") + # FIXME: Ideally, we would build the N32 library too. + if("${COMPILER_RT_MIPS_EL}" AND ("${COMPILER_RT_MIPS32R6}" OR "${COMPILER_RT_MIPS64R6}")) + test_target_arch(mipsel "" "-mips32r6" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64") + test_target_arch(mips64el "" "-mips64r6" "-mabi=64") + elseif("${COMPILER_RT_MIPS_EL}") + test_target_arch(mipsel "" "-mips32r2" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64") + test_target_arch(mips64el "" "-mips64r2" "-mabi=64") + elseif("${COMPILER_RT_MIPS32R6}" OR "${COMPILER_RT_MIPS64R6}") + test_target_arch(mips "" "-mips32r6" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64") + test_target_arch(mips64 "" "-mips64r6" "-mabi=64") + else() + test_target_arch(mips "" "-mips32r2" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64") + test_target_arch(mips64 "" "-mips64r2" "-mabi=64") + endif() elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "arm") if(WIN32) test_target_arch(arm "" "" "") else() + test_target_arch(armv4t "" "-march=armv4t" "-mfloat-abi=soft") + test_target_arch(armv6m "" "-march=armv6m" "-mfloat-abi=soft") test_target_arch(arm "" "-march=armv7-a" "-mfloat-abi=soft") test_target_arch(armhf "" "-march=armv7-a" "-mfloat-abi=hard") - test_target_arch(armv6m "" "-march=armv6m" "-mfloat-abi=soft") endif() + elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "avr") + test_target_arch(avr "__AVR__" "--target=avr") elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "aarch32") test_target_arch(aarch32 "" "-march=armv8-a") elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "aarch64") diff --git a/gnu/llvm/compiler-rt/cmake/builtin-config-ix.cmake b/gnu/llvm/compiler-rt/cmake/builtin-config-ix.cmake index fe5661b7763..e045c81a0f7 100644 --- a/gnu/llvm/compiler-rt/cmake/builtin-config-ix.cmake +++ b/gnu/llvm/compiler-rt/cmake/builtin-config-ix.cmake @@ -10,7 +10,8 @@ builtin_check_c_compiler_flag(-fPIE COMPILER_RT_HAS_FPIE_FLAG) builtin_check_c_compiler_flag(-fno-builtin COMPILER_RT_HAS_FNO_BUILTIN_FLAG) builtin_check_c_compiler_flag(-std=c11 COMPILER_RT_HAS_STD_C11_FLAG) builtin_check_c_compiler_flag(-fvisibility=hidden COMPILER_RT_HAS_VISIBILITY_HIDDEN_FLAG) -builtin_check_c_compiler_flag(-ffreestanding COMPILER_RT_HAS_FREESTANDING_FLAG) +builtin_check_c_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG) +builtin_check_c_compiler_flag(-ffreestanding COMPILER_RT_HAS_FFREESTANDING_FLAG) builtin_check_c_compiler_flag(-fxray-instrument COMPILER_RT_HAS_XRAY_COMPILER_FLAG) builtin_check_c_compiler_source(COMPILER_RT_HAS_ATOMIC_KEYWORD @@ -21,14 +22,6 @@ int foo(int x, int y) { } ") -builtin_check_c_compiler_source(COMPILER_RT_HAS_FLOAT16 -" -_Float16 foo(_Float16 x) { - return x; -} -" -) - builtin_check_c_compiler_source(COMPILER_RT_HAS_ASM_LSE " asm(\".arch armv8-a+lse\"); @@ -36,13 +29,15 @@ asm(\"cas w0, w1, [x2]\"); ") set(ARM64 aarch64) -set(ARM32 arm armhf armv6m armv7m armv7em armv7 armv7s armv7k armv8m.main armv8.1m.main) +set(ARM32 arm armhf armv4t armv5te armv6 armv6m armv7m armv7em armv7 armv7s armv7k armv8m.main armv8.1m.main) +set(AVR avr) set(HEXAGON hexagon) set(X86 i386) set(X86_64 x86_64) +set(LOONGARCH64 loongarch64) set(MIPS32 mips mipsel) set(MIPS64 mips64 mips64el) -set(PPC32 powerpc) +set(PPC32 powerpc powerpcspe) set(PPC64 powerpc64 powerpc64le) set(RISCV32 riscv32) set(RISCV64 riscv64) @@ -59,10 +54,10 @@ if(APPLE) endif() set(ALL_BUILTIN_SUPPORTED_ARCH - ${X86} ${X86_64} ${ARM32} ${ARM64} + ${X86} ${X86_64} ${ARM32} ${ARM64} ${AVR} ${HEXAGON} ${MIPS32} ${MIPS64} ${PPC32} ${PPC64} ${RISCV32} ${RISCV64} ${SPARC} ${SPARCV9} - ${WASM32} ${WASM64} ${VE}) + ${WASM32} ${WASM64} ${VE} ${LOONGARCH64}) include(CompilerRTUtils) include(CompilerRTDarwinUtils) @@ -82,7 +77,8 @@ if(APPLE) execute_process(COMMAND /usr/libexec/PlistBuddy -c "Print :SupportedTargets:${os}:Archs" ${sdk_path}/SDKSettings.plist OUTPUT_VARIABLE SDK_SUPPORTED_ARCHS - RESULT_VARIABLE PLIST_ERROR) + RESULT_VARIABLE PLIST_ERROR + ERROR_QUIET) if (PLIST_ERROR EQUAL 0 AND SDK_SUPPORTED_ARCHS MATCHES " ${arch}\n") message(STATUS "Found ${arch} support in ${sdk_path}/SDKSettings.plist") @@ -94,7 +90,7 @@ if(APPLE) endfunction() set(DARWIN_EMBEDDED_PLATFORMS) - set(DARWIN_osx_BUILTIN_MIN_VER 10.5) + set(DARWIN_osx_BUILTIN_MIN_VER 10.7) set(DARWIN_osx_BUILTIN_MIN_VER_FLAG -mmacosx-version-min=${DARWIN_osx_BUILTIN_MIN_VER}) set(DARWIN_osx_BUILTIN_ALL_POSSIBLE_ARCHS ${X86} ${X86_64}) @@ -114,6 +110,10 @@ if(APPLE) ${DARWIN_ios_MIN_VER_FLAG}=${DARWIN_ios_BUILTIN_MIN_VER}) set(DARWIN_ios_BUILTIN_ALL_POSSIBLE_ARCHS ${ARM64} ${ARM32}) set(DARWIN_iossim_BUILTIN_ALL_POSSIBLE_ARCHS ${X86} ${X86_64}) + find_darwin_sdk_version(iossim_sdk_version "iphonesimulator") + if ("${iossim_sdk_version}" VERSION_GREATER 14.0 OR "${iossim_sdk_version}" VERSION_EQUAL 14.0) + list(APPEND DARWIN_iossim_BUILTIN_ALL_POSSIBLE_ARCHS arm64) + endif() endif() if(COMPILER_RT_ENABLE_WATCHOS) list(APPEND DARWIN_EMBEDDED_PLATFORMS watchos) @@ -123,6 +123,10 @@ if(APPLE) ${DARWIN_watchos_MIN_VER_FLAG}=${DARWIN_watchos_BUILTIN_MIN_VER}) set(DARWIN_watchos_BUILTIN_ALL_POSSIBLE_ARCHS armv7 armv7k arm64_32) set(DARWIN_watchossim_BUILTIN_ALL_POSSIBLE_ARCHS ${X86}) + find_darwin_sdk_version(watchossim_sdk_version "watchsimulator") + if ("${watchossim_sdk_version}" VERSION_GREATER 7.0 OR "${watchossim_sdk_version}" VERSION_EQUAL 7.0) + list(APPEND DARWIN_watchossim_BUILTIN_ALL_POSSIBLE_ARCHS arm64) + endif() endif() if(COMPILER_RT_ENABLE_TVOS) list(APPEND DARWIN_EMBEDDED_PLATFORMS tvos) @@ -132,6 +136,10 @@ if(APPLE) ${DARWIN_tvos_MIN_VER_FLAG}=${DARWIN_tvos_BUILTIN_MIN_VER}) set(DARWIN_tvos_BUILTIN_ALL_POSSIBLE_ARCHS armv7 arm64) set(DARWIN_tvossim_BUILTIN_ALL_POSSIBLE_ARCHS ${X86} ${X86_64}) + find_darwin_sdk_version(tvossim_sdk_version "appletvsimulator") + if ("${tvossim_sdk_version}" VERSION_GREATER 14.0 OR "${tvossim_sdk_version}" VERSION_EQUAL 14.0) + list(APPEND DARWIN_tvossim_BUILTIN_ALL_POSSIBLE_ARCHS arm64) + endif() endif() set(BUILTIN_SUPPORTED_OS osx) diff --git a/gnu/llvm/compiler-rt/cmake/config-ix.cmake b/gnu/llvm/compiler-rt/cmake/config-ix.cmake index 39b9120f00a..5f51befc197 100644 --- a/gnu/llvm/compiler-rt/cmake/config-ix.cmake +++ b/gnu/llvm/compiler-rt/cmake/config-ix.cmake @@ -1,22 +1,30 @@ include(CMakePushCheckState) +include(LLVMCheckCompilerLinkerFlag) include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) include(CheckIncludeFiles) include(CheckLibraryExists) +include(LLVMCheckCompilerLinkerFlag) include(CheckSymbolExists) include(TestBigEndian) -function(compiler_rt_check_linker_flag flag out_var) - cmake_push_check_state() - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${flag}") - check_cxx_compiler_flag("" ${out_var}) - cmake_pop_check_state() -endfunction() +# The compiler driver may be implicitly trying to link against libunwind. +# This is normally ok (libcxx relies on an unwinder), but if libunwind is +# built in the same cmake invocation as compiler-rt and we're using the +# in tree version of runtimes, we'd be linking against the just-built +# libunwind (and the compiler implicit -lunwind wouldn't succeed as the newly +# built libunwind isn't installed yet). For those cases, it'd be good to +# link with --uwnindlib=none. Check if that option works. +llvm_check_compiler_linker_flag(C "--unwindlib=none" CXX_SUPPORTS_UNWINDLIB_NONE_FLAG) check_library_exists(c fopen "" COMPILER_RT_HAS_LIBC) if (COMPILER_RT_USE_BUILTINS_LIBRARY) include(HandleCompilerRT) - find_compiler_rt_library(builtins "" COMPILER_RT_BUILTINS_LIBRARY) + find_compiler_rt_library(builtins COMPILER_RT_BUILTINS_LIBRARY + FLAGS ${SANITIZER_COMMON_FLAGS}) + # TODO(PR51389): We should check COMPILER_RT_BUILTINS_LIBRARY and report an + # error if the value is NOTFOUND rather than silenty continuing but we first + # need to fix find_compiler_rt_library on Darwin. else() if (ANDROID) check_library_exists(gcc __gcc_personality_v0 "" COMPILER_RT_HAS_GCC_LIB) @@ -25,14 +33,17 @@ else() endif() endif() -check_c_compiler_flag(-nodefaultlibs COMPILER_RT_HAS_NODEFAULTLIBS_FLAG) -if (COMPILER_RT_HAS_NODEFAULTLIBS_FLAG) +check_c_compiler_flag(-nodefaultlibs C_SUPPORTS_NODEFAULTLIBS_FLAG) +if (C_SUPPORTS_NODEFAULTLIBS_FLAG) set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs") if (COMPILER_RT_HAS_LIBC) list(APPEND CMAKE_REQUIRED_LIBRARIES c) endif () if (COMPILER_RT_USE_BUILTINS_LIBRARY) - list(APPEND CMAKE_REQUIRED_LIBRARIES "${COMPILER_RT_BUILTINS_LIBRARY}") + # TODO: remote this check once we address PR51389. + if (${COMPILER_RT_BUILTINS_LIBRARY}) + list(APPEND CMAKE_REQUIRED_LIBRARIES "${COMPILER_RT_BUILTINS_LIBRARY}") + endif() elseif (COMPILER_RT_HAS_GCC_S_LIB) list(APPEND CMAKE_REQUIRED_LIBRARIES gcc_s) elseif (COMPILER_RT_HAS_GCC_LIB) @@ -57,6 +68,7 @@ endif () check_c_compiler_flag(-ffreestanding COMPILER_RT_HAS_FFREESTANDING_FLAG) check_c_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG) check_c_compiler_flag(-std=c11 COMPILER_RT_HAS_STD_C11_FLAG) +check_c_compiler_flag(-fcf-protection=full COMPILER_RT_HAS_FCF_PROTECTION_FLAG) check_cxx_compiler_flag(-fPIC COMPILER_RT_HAS_FPIC_FLAG) check_cxx_compiler_flag(-fPIE COMPILER_RT_HAS_FPIE_FLAG) check_cxx_compiler_flag(-fno-builtin COMPILER_RT_HAS_FNO_BUILTIN_FLAG) @@ -69,17 +81,19 @@ check_cxx_compiler_flag(-fvisibility=hidden COMPILER_RT_HAS_FVISIBILITY_HIDDEN_ check_cxx_compiler_flag(-frtti COMPILER_RT_HAS_FRTTI_FLAG) check_cxx_compiler_flag(-fno-rtti COMPILER_RT_HAS_FNO_RTTI_FLAG) check_cxx_compiler_flag("-Werror -fno-function-sections" COMPILER_RT_HAS_FNO_FUNCTION_SECTIONS_FLAG) -check_cxx_compiler_flag(-std=c++14 COMPILER_RT_HAS_STD_CXX14_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(-fno-profile-generate COMPILER_RT_HAS_FNO_PROFILE_GENERATE_FLAG) check_cxx_compiler_flag(-fno-profile-instr-generate COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG) check_cxx_compiler_flag(-fno-profile-instr-use COMPILER_RT_HAS_FNO_PROFILE_INSTR_USE_FLAG) +check_cxx_compiler_flag(-fno-coverage-mapping COMPILER_RT_HAS_FNO_COVERAGE_MAPPING_FLAG) +check_cxx_compiler_flag("-Werror -mcrc32" COMPILER_RT_HAS_MCRC32_FLAG) check_cxx_compiler_flag("-Werror -msse3" COMPILER_RT_HAS_MSSE3_FLAG) check_cxx_compiler_flag("-Werror -msse4.2" COMPILER_RT_HAS_MSSE4_2_FLAG) check_cxx_compiler_flag(--sysroot=. COMPILER_RT_HAS_SYSROOT_FLAG) check_cxx_compiler_flag("-Werror -mcrc" COMPILER_RT_HAS_MCRC_FLAG) check_cxx_compiler_flag(-fno-partial-inlining COMPILER_RT_HAS_FNO_PARTIAL_INLINING_FLAG) +check_cxx_compiler_flag(-Werror -ftrivial-auto-var-init=pattern COMPILER_RT_HAS_TRIVIAL_AUTO_INIT) if(NOT WIN32 AND NOT CYGWIN) # MinGW warns if -fvisibility-inlines-hidden is used. @@ -108,17 +122,41 @@ check_cxx_compiler_flag("-Werror -Wvariadic-macros" COMPILER_RT_HAS_WVARIADIC check_cxx_compiler_flag("-Werror -Wunused-parameter" COMPILER_RT_HAS_WUNUSED_PARAMETER_FLAG) check_cxx_compiler_flag("-Werror -Wcovered-switch-default" COMPILER_RT_HAS_WCOVERED_SWITCH_DEFAULT_FLAG) check_cxx_compiler_flag("-Werror -Wsuggest-override" COMPILER_RT_HAS_WSUGGEST_OVERRIDE_FLAG) +check_cxx_compiler_flag("-Werror -Wthread-safety" COMPILER_RT_HAS_WTHREAD_SAFETY_FLAG) +check_cxx_compiler_flag("-Werror -Wthread-safety-reference" COMPILER_RT_HAS_WTHREAD_SAFETY_REFERENCE_FLAG) +check_cxx_compiler_flag("-Werror -Wthread-safety-beta" COMPILER_RT_HAS_WTHREAD_SAFETY_BETA_FLAG) check_cxx_compiler_flag(-Wno-pedantic COMPILER_RT_HAS_WNO_PEDANTIC) +check_cxx_compiler_flag(-Wno-format COMPILER_RT_HAS_WNO_FORMAT) +check_cxx_compiler_flag(-Wno-format-pedantic COMPILER_RT_HAS_WNO_FORMAT_PEDANTIC) + +check_cxx_compiler_flag("/experimental:external /external:W0" COMPILER_RT_HAS_EXTERNAL_FLAG) check_cxx_compiler_flag(/W4 COMPILER_RT_HAS_W4_FLAG) check_cxx_compiler_flag(/WX COMPILER_RT_HAS_WX_FLAG) check_cxx_compiler_flag(/wd4146 COMPILER_RT_HAS_WD4146_FLAG) +check_cxx_compiler_flag(/wd4206 COMPILER_RT_HAS_WD4206_FLAG) check_cxx_compiler_flag(/wd4291 COMPILER_RT_HAS_WD4291_FLAG) check_cxx_compiler_flag(/wd4221 COMPILER_RT_HAS_WD4221_FLAG) check_cxx_compiler_flag(/wd4391 COMPILER_RT_HAS_WD4391_FLAG) check_cxx_compiler_flag(/wd4722 COMPILER_RT_HAS_WD4722_FLAG) check_cxx_compiler_flag(/wd4800 COMPILER_RT_HAS_WD4800_FLAG) +check_cxx_compiler_flag(-Werror -Warray-bounds COMPILER_RT_HAS_ARRAY_BOUNDS_FLAG) +check_cxx_compiler_flag(-Werror -Wuninitialized COMPILER_RT_HAS_UNINITIALIZED_FLAG) +check_cxx_compiler_flag(-Werror -Wshadow COMPILER_RT_HAS_SHADOW_FLAG) +check_cxx_compiler_flag(-Werror -Wempty-body COMPILER_RT_HAS_EMPTY_BODY_FLAG) +check_cxx_compiler_flag(-Werror -Wsizeof-pointer-memaccess COMPILER_RT_HAS_SIZEOF_POINTER_MEMACCESS_FLAG) +check_cxx_compiler_flag(-Werror -Wsizeof-array-argument COMPILER_RT_HAS_SIZEOF_ARRAY_ARGUMENT_FLAG) +check_cxx_compiler_flag(-Werror -Wsuspicious-memaccess COMPILER_RT_HAS_SUSPICIOUS_MEMACCESS_FLAG) +check_cxx_compiler_flag(-Werror -Wbuiltin-memcpy-chk-size COMPILER_RT_HAS_BUILTIN_MEMCPY_CHK_SIZE_FLAG) +check_cxx_compiler_flag(-Werror -Warray-bounds-pointer-arithmetic COMPILER_RT_HAS_ARRAY_BOUNDS_POINTER_ARITHMETIC_FLAG) +check_cxx_compiler_flag(-Werror -Wreturn-stack-address COMPILER_RT_HAS_RETURN_STACK_ADDRESS_FLAG) +check_cxx_compiler_flag(-Werror -Wsizeof-array-decay COMPILER_RT_HAS_SIZEOF_ARRAY_DECAY_FLAG) +check_cxx_compiler_flag(-Werror -Wformat-insufficient-args COMPILER_RT_HAS_FORMAT_INSUFFICIENT_ARGS_FLAG) +check_cxx_compiler_flag(-Werror -Wformat-security COMPILER_RT_HAS_BUILTIN_FORMAL_SECURITY_FLAG) +check_cxx_compiler_flag(-Werror -Wsizeof-array-div COMPILER_RT_HAS_SIZEOF_ARRAY_DIV_FLAG) +check_cxx_compiler_flag(-Werror -Wsizeof-pointer-div COMPILER_RT_HAS_SIZEOF_POINTER_DIV_FLAG) + # Symbols. check_symbol_exists(__func__ "" COMPILER_RT_HAS_FUNC_SYMBOL) @@ -157,11 +195,13 @@ check_library_exists(c++ __cxa_throw "" COMPILER_RT_HAS_LIBCXX) check_library_exists(stdc++ __cxa_throw "" COMPILER_RT_HAS_LIBSTDCXX) # Linker flags. -compiler_rt_check_linker_flag("-Wl,-z,text" COMPILER_RT_HAS_Z_TEXT) -compiler_rt_check_linker_flag("-fuse-ld=lld" COMPILER_RT_HAS_FUSE_LD_LLD_FLAG) +llvm_check_compiler_linker_flag(C "-Wl,-z,text" COMPILER_RT_HAS_Z_TEXT) +llvm_check_compiler_linker_flag(C "-fuse-ld=lld" COMPILER_RT_HAS_FUSE_LD_LLD_FLAG) -set(VERS_COMPAT_OPTION "-Wl,-z,gnu-version-script-compat") -compiler_rt_check_linker_flag("${VERS_COMPAT_OPTION}" COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT) +if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS") + set(VERS_COMPAT_OPTION "-Wl,-z,gnu-version-script-compat") + llvm_check_compiler_linker_flag(C "${VERS_COMPAT_OPTION}" COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT) +endif() set(DUMMY_VERS ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/dummy.vers) file(WRITE ${DUMMY_VERS} "{};") @@ -171,10 +211,10 @@ if(COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT) # -z gnu-version-script-compat. string(APPEND VERS_OPTION " ${VERS_COMPAT_OPTION}") endif() -compiler_rt_check_linker_flag("${VERS_OPTION}" COMPILER_RT_HAS_VERSION_SCRIPT) +llvm_check_compiler_linker_flag(C "${VERS_OPTION}" COMPILER_RT_HAS_VERSION_SCRIPT) if(ANDROID) - compiler_rt_check_linker_flag("-Wl,-z,global" COMPILER_RT_HAS_Z_GLOBAL) + llvm_check_compiler_linker_flag(C "-Wl,-z,global" COMPILER_RT_HAS_Z_GLOBAL) check_library_exists(log __android_log_write "" COMPILER_RT_HAS_LIBLOG) endif() @@ -188,12 +228,14 @@ set(COMPILER_RT_SUPPORTED_ARCH) # runtime libraries supported by our current compilers cross-compiling # abilities. set(SIMPLE_SOURCE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/simple.cc) -file(WRITE ${SIMPLE_SOURCE} "#include \n#include \nint main() { printf(\"hello, world\"); }\n") +file(WRITE ${SIMPLE_SOURCE} "#include \n#include \nint main(void) { printf(\"hello, world\"); }\n") # Detect whether the current target platform is 32-bit or 64-bit, and setup # the correct commandline flags needed to attempt to target 32-bit and 64-bit. +# AVR and MSP430 are omitted since they have 16-bit pointers. if (NOT CMAKE_SIZEOF_VOID_P EQUAL 4 AND - NOT CMAKE_SIZEOF_VOID_P EQUAL 8) + NOT CMAKE_SIZEOF_VOID_P EQUAL 8 AND + NOT ${arch} MATCHES "avr|msp430") message(FATAL_ERROR "Please use architecture with 4 or 8 byte pointers.") endif() @@ -216,11 +258,27 @@ function(get_target_flags_for_arch arch out_var) endif() endfunction() +# Returns a list of architecture specific target ldflags in @out_var list. +function(get_target_link_flags_for_arch arch out_var) + list(FIND COMPILER_RT_SUPPORTED_ARCH ${arch} ARCH_INDEX) + if(ARCH_INDEX EQUAL -1) + message(FATAL_ERROR "Unsupported architecture: ${arch}") + else() + # Workaround for direct calls to __tls_get_addr on Solaris/amd64. + if(OS_NAME MATCHES "SunOS" AND ${arch} MATCHES x86_64) + set(${out_var} "-Wl,-z,relax=transtls" PARENT_SCOPE) + endif() + endif() +endfunction() + # Returns a compiler and CFLAGS that should be used to run tests for the # specific architecture. When cross-compiling, this is controled via # COMPILER_RT_TEST_COMPILER and COMPILER_RT_TEST_COMPILER_CFLAGS. macro(get_test_cc_for_arch arch cc_out cflags_out) - if(ANDROID OR ${arch} MATCHES "arm|aarch64|riscv32|riscv64") + if (NOT ${ARGC} EQUAL 3) + message(FATAL_ERROR "got too many args. expected 3, got ${ARGC} (namely: ${ARGV})") + endif() + if(ANDROID OR (NOT APPLE AND ${arch} MATCHES "arm|aarch64|riscv32|riscv64")) # This is only true if we are cross-compiling. # Build all tests with host compiler and use host tools. set(${cc_out} ${COMPILER_RT_TEST_COMPILER}) @@ -243,7 +301,35 @@ function(get_test_cflags_for_apple_platform platform arch cflags_out) endif() set(test_cflags "") get_target_flags_for_arch(${arch} test_cflags) - list(APPEND test_cflags ${DARWIN_${platform}_CFLAGS}) + + if (NOT "${arch}" STREQUAL "arm64e") + list(APPEND test_cflags ${DARWIN_${platform}_CFLAGS}) + else() + # arm64e is not currently ABI stable so we need to build for the + # OS version being tested. Rather than querying the device under test + # we use the SDK version which "should" be the same as the + # device under test (it is a configuration error for these not to match). + # FIXME(dliew): We can remove this if we build the runtimes with the appropriate + # deployment target for arm64e. + foreach (flag ${DARWIN_${platform}_CFLAGS}) + if ("${flag}" MATCHES "^${DARWIN_${platform}_MIN_VER_FLAG}=.+") + # Find the SDK version + get_xcrun_platform_from_apple_platform("${platform}" xcrun_platform_name) + # TODO(dliew): Remove this check once get_xcrun_platform_from_apple_platform + # emits a fatal error for unrecognised platforms. + if (NOT "${xcrun_platform_name}" STREQUAL "") + find_darwin_sdk_version(platform_sdk_version "${xcrun_platform_name}") + # Patch flag with correct deployment target + set(replacement_flag "${DARWIN_${platform}_MIN_VER_FLAG}=${platform_sdk_version}") + list(APPEND test_cflags "${replacement_flag}") + endif() + else() + # Copy through + list(APPEND test_cflags "${flag}") + endif() + endforeach() + endif() + string(REPLACE ";" " " test_cflags_str "${test_cflags}") string(APPEND test_cflags_str "${COMPILER_RT_TEST_COMPILER_CFLAGS}") set(${cflags_out} "${test_cflags_str}" PARENT_SCOPE) @@ -272,81 +358,32 @@ function(is_valid_apple_platform platform is_valid_out) set(${is_valid_out} ${is_valid} PARENT_SCOPE) endfunction() -set(ARM64 aarch64) -set(ARM32 arm armhf) -set(HEXAGON hexagon) -set(X86 i386) -set(X86_64 x86_64) -set(MIPS32 mips mipsel) -set(MIPS64 mips64 mips64el) -set(PPC32 powerpc) -set(PPC64 powerpc64 powerpc64le) -set(RISCV32 riscv32) -set(RISCV64 riscv64) -set(S390X s390x) -set(SPARC sparc) -set(SPARCV9 sparcv9) -set(WASM32 wasm32) -set(WASM64 wasm64) -set(VE ve) - -if(APPLE) - set(ARM64 arm64) - set(ARM32 armv7 armv7s armv7k) - set(X86_64 x86_64 x86_64h) -endif() - -set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64} ${RISCV64} - ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9}) -set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} - ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9}) -set(ALL_CRT_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV32} ${RISCV64} ${VE}) -set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) - -if(ANDROID) - set(OS_NAME "Android") -else() - set(OS_NAME "${CMAKE_SYSTEM_NAME}") -endif() - -if(OS_NAME MATCHES "Linux") - set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${S390X}) -elseif (OS_NAME MATCHES "Windows") - set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64}) -elseif(OS_NAME MATCHES "Android") - set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}) -else() - set(ALL_FUZZER_SUPPORTED_ARCH ${X86_64} ${ARM64}) -endif() - -set(ALL_GWP_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}) -if(APPLE) - set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64}) -else() - set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64} ${ARM32} ${PPC64} ${S390X} ${RISCV64}) -endif() -set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}) -set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64}) -set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64}) -set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64} - ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9}) -set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}) -set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} - ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9}) -set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64}) -set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64}) -set(ALL_SCUDO_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64}) -set(ALL_SCUDO_STANDALONE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64}) -if(APPLE) -set(ALL_XRAY_SUPPORTED_ARCH ${X86_64}) -else() -set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le) -endif() -set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64}) +# Maps the Apple platform name used in Compiler-rt's CMake code +# to the name recognised by xcrun's `--sdk` argument +function(get_xcrun_platform_from_apple_platform platform out_var) + set(xcrun_platform "") + if ("${platform}" STREQUAL "osx") + set(xcrun_platform "macosx") + elseif ("${platform}" STREQUAL "iossim") + set(xcrun_platform "iphonesimulator") + elseif ("${platform}" STREQUAL "ios") + set(xcrun_platform "iphoneos") + elseif ("${platform}" STREQUAL "watchossim") + set(xcrun_platform "watchsimulator") + elseif ("${platform}" STREQUAL "watchos") + set(xcrun_platform "watchos") + elseif ("${platform}" STREQUAL "tvossim") + set(xcrun_platform "appletvsimulator") + elseif ("${platform}" STREQUAL "tvos") + set(xcrun_platform "appletvos") + else() + # TODO(dliew): Make this an error. + message(WARNING "\"${platform}\" is not a handled apple platform") + endif() + set(${out_var} ${xcrun_platform} PARENT_SCOPE) +endfunction() -if (UNIX) -set(ALL_ORC_SUPPORTED_ARCH ${X86_64}) -endif() +include(AllSupportedArchDefs) if(APPLE) include(CompilerRTDarwinUtils) @@ -405,6 +442,9 @@ if(APPLE) set(XRAY_SUPPORTED_OS osx) set(FUZZER_SUPPORTED_OS osx) set(ORC_SUPPORTED_OS osx) + set(UBSAN_SUPPORTED_OS osx) + set(LSAN_SUPPORTED_OS osx) + set(STATS_SUPPORTED_OS osx) # Note: In order to target x86_64h on OS X the minimum deployment target must # be 10.8 or higher. @@ -438,7 +478,7 @@ if(APPLE) -lc++ -lc++abi) - compiler_rt_check_linker_flag("-fapplication-extension" COMPILER_RT_HAS_APP_EXTENSION) + llvm_check_compiler_linker_flag(C "-fapplication-extension" COMPILER_RT_HAS_APP_EXTENSION) if(COMPILER_RT_HAS_APP_EXTENSION) list(APPEND DARWIN_COMMON_LINK_FLAGS "-fapplication-extension") endif() @@ -490,6 +530,10 @@ if(APPLE) list(APPEND PROFILE_SUPPORTED_OS ${platform}sim) list(APPEND TSAN_SUPPORTED_OS ${platform}sim) list(APPEND FUZZER_SUPPORTED_OS ${platform}sim) + list(APPEND ORC_SUPPORTED_OS ${platform}sim) + list(APPEND UBSAN_SUPPORTED_OS ${platform}sim) + list(APPEND LSAN_SUPPORTED_OS ${platform}sim) + list(APPEND STATS_SUPPORTED_OS ${platform}sim) endif() foreach(arch ${DARWIN_${platform}sim_ARCHS}) list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch}) @@ -520,6 +564,10 @@ if(APPLE) list(APPEND TSAN_SUPPORTED_OS ${platform}) endif() list(APPEND FUZZER_SUPPORTED_OS ${platform}) + list(APPEND ORC_SUPPORTED_OS ${platform}) + list(APPEND UBSAN_SUPPORTED_OS ${platform}) + list(APPEND LSAN_SUPPORTED_OS ${platform}) + list(APPEND STATS_SUPPORTED_OS ${platform}) endif() foreach(arch ${DARWIN_${platform}_ARCHS}) list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch}) @@ -529,7 +577,7 @@ if(APPLE) endforeach() endif() - # Explictly disable unsupported Sanitizer configurations. + # Explicitly disable unsupported Sanitizer configurations. list(REMOVE_ITEM FUZZER_SUPPORTED_OS "watchos") list(REMOVE_ITEM FUZZER_SUPPORTED_OS "watchossim") @@ -578,9 +626,6 @@ if(APPLE) list_intersect(CFI_SUPPORTED_ARCH ALL_CFI_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) - list_intersect(SCUDO_SUPPORTED_ARCH - ALL_SCUDO_SUPPORTED_ARCH - SANITIZER_COMMON_SUPPORTED_ARCH) list_intersect(SCUDO_STANDALONE_SUPPORTED_ARCH ALL_SCUDO_STANDALONE_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) @@ -598,7 +643,6 @@ if(APPLE) SANITIZER_COMMON_SUPPORTED_ARCH) else() - filter_available_targets(CRT_SUPPORTED_ARCH ${ALL_CRT_SUPPORTED_ARCH}) # Architectures supported by compiler-rt libraries. filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH ${ALL_SANITIZER_COMMON_SUPPORTED_ARCH}) @@ -621,7 +665,6 @@ else() filter_available_targets(SAFESTACK_SUPPORTED_ARCH ${ALL_SAFESTACK_SUPPORTED_ARCH}) filter_available_targets(CFI_SUPPORTED_ARCH ${ALL_CFI_SUPPORTED_ARCH}) - filter_available_targets(SCUDO_SUPPORTED_ARCH ${ALL_SCUDO_SUPPORTED_ARCH}) filter_available_targets(SCUDO_STANDALONE_SUPPORTED_ARCH ${ALL_SCUDO_STANDALONE_SUPPORTED_ARCH}) filter_available_targets(XRAY_SUPPORTED_ARCH ${ALL_XRAY_SUPPORTED_ARCH}) filter_available_targets(SHADOWCALLSTACK_SUPPORTED_ARCH @@ -631,8 +674,19 @@ else() endif() if (MSVC) + # Allow setting clang-cl's /winsysroot flag. + set(LLVM_WINSYSROOT "" CACHE STRING + "If set, argument to clang-cl's /winsysroot") + + if (LLVM_WINSYSROOT) + set(MSVC_DIA_SDK_DIR "${LLVM_WINSYSROOT}/DIA SDK" CACHE PATH + "Path to the DIA SDK") + else() + set(MSVC_DIA_SDK_DIR "$ENV{VSINSTALLDIR}DIA SDK" CACHE PATH + "Path to the DIA SDK") + endif() + # See if the DIA SDK is available and usable. - set(MSVC_DIA_SDK_DIR "$ENV{VSINSTALLDIR}DIA SDK") if (IS_DIRECTORY ${MSVC_DIA_SDK_DIR}) set(CAN_SYMBOLIZE 1) else() @@ -650,7 +704,7 @@ if(COMPILER_RT_SUPPORTED_ARCH) endif() message(STATUS "Compiler-RT supported architectures: ${COMPILER_RT_SUPPORTED_ARCH}") -set(ALL_SANITIZERS asan;dfsan;msan;hwasan;tsan;safestack;cfi;scudo;ubsan_minimal;gwp_asan) +set(ALL_SANITIZERS asan;dfsan;msan;hwasan;tsan;safestack;cfi;scudo_standalone;ubsan_minimal;gwp_asan) set(COMPILER_RT_SANITIZERS_TO_BUILD all CACHE STRING "sanitizers to build if supported on the target (all;${ALL_SANITIZERS})") list_replace(COMPILER_RT_SANITIZERS_TO_BUILD all "${ALL_SANITIZERS}") @@ -684,12 +738,6 @@ endif() # TODO: Add builtins support. -if (CRT_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux" AND NOT LLVM_USE_SANITIZER) - set(COMPILER_RT_HAS_CRT TRUE) -else() - set(COMPILER_RT_HAS_CRT FALSE) -endif() - if (COMPILER_RT_HAS_SANITIZER_COMMON AND DFSAN_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux") set(COMPILER_RT_HAS_DFSAN TRUE) @@ -712,7 +760,7 @@ else() endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND HWASAN_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux|Android") + OS_NAME MATCHES "Linux|Android|Fuchsia") set(COMPILER_RT_HAS_HWASAN TRUE) else() set(COMPILER_RT_HAS_HWASAN FALSE) @@ -732,13 +780,24 @@ else() set(COMPILER_RT_HAS_PROFILE FALSE) endif() -if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH AND - OS_NAME MATCHES "Darwin|Linux|FreeBSD|Android|NetBSD") - set(COMPILER_RT_HAS_TSAN TRUE) +if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH) + if (OS_NAME MATCHES "Linux|Darwin|FreeBSD|NetBSD") + set(COMPILER_RT_HAS_TSAN TRUE) + elseif (OS_NAME MATCHES "Android" AND ANDROID_PLATFORM_LEVEL GREATER 23) + set(COMPILER_RT_HAS_TSAN TRUE) + else() + set(COMPILER_RT_HAS_TSAN FALSE) + endif() else() set(COMPILER_RT_HAS_TSAN FALSE) endif() +if (OS_NAME MATCHES "Linux|FreeBSD|Windows|NetBSD|SunOS") + set(COMPILER_RT_TSAN_HAS_STATIC_RUNTIME TRUE) +else() + set(COMPILER_RT_TSAN_HAS_STATIC_RUNTIME FALSE) +endif() + if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|Windows|Android|Fuchsia|SunOS") set(COMPILER_RT_HAS_UBSAN TRUE) @@ -767,20 +826,16 @@ else() endif() #TODO(kostyak): add back Android & Fuchsia when the code settles a bit. -if (SCUDO_STANDALONE_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux" AND +if (SCUDO_STANDALONE_SUPPORTED_ARCH AND + COMPILER_RT_BUILD_SANITIZERS AND + "scudo_standalone" IN_LIST COMPILER_RT_SANITIZERS_TO_BUILD AND + OS_NAME MATCHES "Linux" AND COMPILER_RT_HAS_AUXV) set(COMPILER_RT_HAS_SCUDO_STANDALONE TRUE) else() set(COMPILER_RT_HAS_SCUDO_STANDALONE FALSE) endif() -if (COMPILER_RT_HAS_SANITIZER_COMMON AND SCUDO_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux|Android|Fuchsia") - set(COMPILER_RT_HAS_SCUDO TRUE) -else() - set(COMPILER_RT_HAS_SCUDO FALSE) -endif() - if (COMPILER_RT_HAS_SANITIZER_COMMON AND XRAY_SUPPORTED_ARCH AND OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|Fuchsia") set(COMPILER_RT_HAS_XRAY TRUE) @@ -813,7 +868,10 @@ endif() # calling malloc on first use. # TODO(hctim): Enable this on Android again. Looks like it's causing a SIGSEGV # for Scudo and GWP-ASan, further testing needed. -if (COMPILER_RT_HAS_SANITIZER_COMMON AND GWP_ASAN_SUPPORTED_ARCH AND +if (GWP_ASAN_SUPPORTED_ARCH AND + COMPILER_RT_BUILD_GWP_ASAN AND + COMPILER_RT_BUILD_SANITIZERS AND + "gwp_asan" IN_LIST COMPILER_RT_SANITIZERS_TO_BUILD AND OS_NAME MATCHES "Linux") set(COMPILER_RT_HAS_GWP_ASAN TRUE) else() diff --git a/gnu/llvm/compiler-rt/cmake/crt-config-ix.cmake b/gnu/llvm/compiler-rt/cmake/crt-config-ix.cmake new file mode 100644 index 00000000000..066a0edbc56 --- /dev/null +++ b/gnu/llvm/compiler-rt/cmake/crt-config-ix.cmake @@ -0,0 +1,51 @@ +include(BuiltinTests) +include(CheckCSourceCompiles) + +# Make all the tests only check the compiler +set(TEST_COMPILE_ONLY On) + +builtin_check_c_compiler_flag(-fPIC COMPILER_RT_HAS_FPIC_FLAG) +builtin_check_c_compiler_flag(-std=c11 COMPILER_RT_HAS_STD_C11_FLAG) +builtin_check_c_compiler_flag(-Wno-pedantic COMPILER_RT_HAS_WNO_PEDANTIC) +builtin_check_c_compiler_flag(-fno-lto COMPILER_RT_HAS_FNO_LTO_FLAG) +builtin_check_c_compiler_flag(-fno-profile-generate COMPILER_RT_HAS_FNO_PROFILE_GENERATE_FLAG) +builtin_check_c_compiler_flag(-fno-profile-instr-generate COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG) +builtin_check_c_compiler_flag(-fno-profile-instr-use COMPILER_RT_HAS_FNO_PROFILE_INSTR_USE_FLAG) + +if(ANDROID) + set(OS_NAME "Android") +else() + set(OS_NAME "${CMAKE_SYSTEM_NAME}") +endif() + +set(ARM64 aarch64) +set(ARM32 arm armhf) +set(HEXAGON hexagon) +set(X86 i386) +set(X86_64 x86_64) +set(LOONGARCH64 loongarch64) +set(PPC32 powerpc powerpcspe) +set(PPC64 powerpc64 powerpc64le) +set(RISCV32 riscv32) +set(RISCV64 riscv64) +set(VE ve) + +set(ALL_CRT_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} + ${PPC64} ${RISCV32} ${RISCV64} ${VE} ${HEXAGON} ${LOONGARCH64}) + +include(CompilerRTUtils) + +if(NOT APPLE) + if(COMPILER_RT_CRT_STANDALONE_BUILD) + test_targets() + endif() + # Architectures supported by compiler-rt crt library. + filter_available_targets(CRT_SUPPORTED_ARCH ${ALL_CRT_SUPPORTED_ARCH}) + message(STATUS "Supported architectures for crt: ${CRT_SUPPORTED_ARCH}") +endif() + +if (CRT_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux" AND NOT LLVM_USE_SANITIZER) + set(COMPILER_RT_HAS_CRT TRUE) +else() + set(COMPILER_RT_HAS_CRT FALSE) +endif() diff --git a/gnu/llvm/compiler-rt/docs/TestingGuide.rst b/gnu/llvm/compiler-rt/docs/TestingGuide.rst index 4edda6738ac..a1419ede02f 100644 --- a/gnu/llvm/compiler-rt/docs/TestingGuide.rst +++ b/gnu/llvm/compiler-rt/docs/TestingGuide.rst @@ -31,23 +31,24 @@ REQUIRES, XFAIL, etc. Sometimes it is necessary to restrict a test to a specific target or mark it as an "expected fail" or XFAIL. This is normally achieved using ``REQUIRES:`` or -``XFAIL:`` with a substring of LLVM's default target triple. Unfortunately, the +``XFAIL:`` and the ``target=`` feature, typically with a regular +expression matching an appropriate substring of the triple. Unfortunately, the behaviour of this is somewhat quirky in compiler-rt. There are two main pitfalls to avoid. -The first pitfall is that these directives perform a substring match on the -triple and as such ``XFAIL: mips`` affects more triples than expected. For -example, ``mips-linux-gnu``, ``mipsel-linux-gnu``, ``mips64-linux-gnu``, and -``mips64el-linux-gnu`` will all match a ``XFAIL: mips`` directive. Including a -trailing ``-`` such as in ``XFAIL: mips-`` can help to mitigate this quirk but -even that has issues as described below. +The first pitfall is that these regular expressions may inadvertently match +more triples than expected. For example, ``XFAIL: target=mips{{.*}}`` matches +``mips-linux-gnu``, ``mipsel-linux-gnu``, ``mips64-linux-gnu``, and +``mips64el-linux-gnu``. Including a trailing ``-`` such as in +``XFAIL: target=mips-{{.*}}`` can help to mitigate this quirk but even that has +issues as described below. The second pitfall is that the default target triple is often inappropriate for compiler-rt tests since compiler-rt tests may be compiled for multiple targets. For example, a typical build on an ``x86_64-linux-gnu`` host will often run the -tests for both x86_64 and i386. In this situation ``XFAIL: x86_64`` will mark -both the x86_64 and i386 tests as an expected failure while ``XFAIL: i386`` -will have no effect at all. +tests for both x86_64 and i386. In this situation ``XFAIL: target=x86_64{{{.*}}`` +will mark both the x86_64 and i386 tests as an expected failure while +``XFAIL: target=i386{{.*}}`` will have no effect at all. To remedy both pitfalls, compiler-rt tests provide a feature string which can be used to specify a single target. This string is of the form diff --git a/gnu/llvm/compiler-rt/include/CMakeLists.txt b/gnu/llvm/compiler-rt/include/CMakeLists.txt index 7b415f0b88a..78427beedb3 100644 --- a/gnu/llvm/compiler-rt/include/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/include/CMakeLists.txt @@ -23,6 +23,7 @@ endif(COMPILER_RT_BUILD_SANITIZERS) if (COMPILER_RT_BUILD_MEMPROF) set(MEMPROF_HEADERS sanitizer/memprof_interface.h + profile/MemProfData.inc ) endif(COMPILER_RT_BUILD_MEMPROF) @@ -34,6 +35,12 @@ if (COMPILER_RT_BUILD_XRAY) ) endif(COMPILER_RT_BUILD_XRAY) +if (COMPILER_RT_BUILD_ORC) + set(ORC_HEADERS + orc_rt/c_api.h + ) +endif(COMPILER_RT_BUILD_ORC) + if (COMPILER_RT_BUILD_PROFILE) set(PROFILE_HEADERS profile/InstrProfData.inc @@ -45,6 +52,7 @@ set(COMPILER_RT_HEADERS ${FUZZER_HEADERS} ${MEMPROF_HEADERS} ${XRAY_HEADERS} + ${ORC_HEADERS} ${PROFILE_HEADERS}) set(output_dir ${COMPILER_RT_OUTPUT_DIR}/include) @@ -75,11 +83,23 @@ install(FILES ${FUZZER_HEADERS} COMPONENT compiler-rt-headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ DESTINATION ${COMPILER_RT_INSTALL_INCLUDE_DIR}/fuzzer) +# Install memprof headers. +if (COMPILER_RT_BUILD_MEMPROF) + install(FILES sanitizer/memprof_interface.h + COMPONENT compiler-rt-headers + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ + DESTINATION ${COMPILER_RT_INSTALL_INCLUDE_DIR}/sanitizer) +endif(COMPILER_RT_BUILD_MEMPROF) # Install xray headers. install(FILES ${XRAY_HEADERS} COMPONENT compiler-rt-headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ DESTINATION ${COMPILER_RT_INSTALL_INCLUDE_DIR}/xray) +# Install ORC headers. +install(FILES ${ORC_HEADERS} + COMPONENT compiler-rt-headers + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ + DESTINATION ${COMPILER_RT_INSTALL_INCLUDE_DIR}/orc) # Install profile headers. install(FILES ${PROFILE_HEADERS} COMPONENT compiler-rt-headers diff --git a/gnu/llvm/compiler-rt/include/orc_rt/c_api.h b/gnu/llvm/compiler-rt/include/orc_rt/c_api.h new file mode 100644 index 00000000000..96d01df15e8 --- /dev/null +++ b/gnu/llvm/compiler-rt/include/orc_rt/c_api.h @@ -0,0 +1,205 @@ +/*===- c_api.h - C API for the ORC runtime ------------------------*- C -*-===*\ +|* *| +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *| +|* Exceptions. *| +|* See https://llvm.org/LICENSE.txt for license information. *| +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C API for the ORC runtime *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef ORC_RT_C_API_H +#define ORC_RT_C_API_H + +#include +#include +#include +#include + +/* Helper to suppress strict prototype warnings. */ +#ifdef __clang__ +#define ORC_RT_C_STRICT_PROTOTYPES_BEGIN \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic error \"-Wstrict-prototypes\"") +#define ORC_RT_C_STRICT_PROTOTYPES_END _Pragma("clang diagnostic pop") +#else +#define ORC_RT_C_STRICT_PROTOTYPES_BEGIN +#define ORC_RT_C_STRICT_PROTOTYPES_END +#endif + +/* Helper to wrap C code for C++ */ +#ifdef __cplusplus +#define ORC_RT_C_EXTERN_C_BEGIN \ + extern "C" { \ + ORC_RT_C_STRICT_PROTOTYPES_BEGIN +#define ORC_RT_C_EXTERN_C_END \ + ORC_RT_C_STRICT_PROTOTYPES_END \ + } +#else +#define ORC_RT_C_EXTERN_C_BEGIN ORC_RT_C_STRICT_PROTOTYPES_BEGIN +#define ORC_RT_C_EXTERN_C_END ORC_RT_C_STRICT_PROTOTYPES_END +#endif + +ORC_RT_C_EXTERN_C_BEGIN + +typedef union { + char *ValuePtr; + char Value[sizeof(char *)]; +} __orc_rt_CWrapperFunctionResultDataUnion; + +/** + * __orc_rt_CWrapperFunctionResult is a kind of C-SmallVector with an + * out-of-band error state. + * + * If Size == 0 and Data.ValuePtr is non-zero then the value is in the + * 'out-of-band error' state, and Data.ValuePtr points at a malloc-allocated, + * null-terminated string error message. + * + * If Size <= sizeof(__orc_rt_CWrapperFunctionResultData) then the value is in + * the 'small' state and the content is held in the first Size bytes of + * Data.Value. + * + * If Size > sizeof(OrtRTCWrapperFunctionResultData) then the value is in the + * 'large' state and the content is held in the first Size bytes of the + * memory pointed to by Data.ValuePtr. This memory must have been allocated by + * malloc, and will be freed with free when this value is destroyed. + */ +typedef struct { + __orc_rt_CWrapperFunctionResultDataUnion Data; + size_t Size; +} __orc_rt_CWrapperFunctionResult; + +typedef struct __orc_rt_CSharedOpaqueJITProcessControl + *__orc_rt_SharedJITProcessControlRef; + +/** + * Zero-initialize an __orc_rt_CWrapperFunctionResult. + */ +static inline void +__orc_rt_CWrapperFunctionResultInit(__orc_rt_CWrapperFunctionResult *R) { + R->Size = 0; + R->Data.ValuePtr = 0; +} + +/** + * Create an __orc_rt_CWrapperFunctionResult with an uninitialized buffer of + * size Size. The buffer is returned via the DataPtr argument. + */ +static inline __orc_rt_CWrapperFunctionResult +__orc_rt_CWrapperFunctionResultAllocate(size_t Size) { + __orc_rt_CWrapperFunctionResult R; + R.Size = Size; + // If Size is 0 ValuePtr must be 0 or it is considered an out-of-band error. + R.Data.ValuePtr = 0; + if (Size > sizeof(R.Data.Value)) + R.Data.ValuePtr = (char *)malloc(Size); + return R; +} + +/** + * Create an __orc_rt_WrapperFunctionResult from the given data range. + */ +static inline __orc_rt_CWrapperFunctionResult +__orc_rt_CreateCWrapperFunctionResultFromRange(const char *Data, size_t Size) { + __orc_rt_CWrapperFunctionResult R; + R.Size = Size; + if (R.Size > sizeof(R.Data.Value)) { + char *Tmp = (char *)malloc(Size); + memcpy(Tmp, Data, Size); + R.Data.ValuePtr = Tmp; + } else + memcpy(R.Data.Value, Data, Size); + return R; +} + +/** + * Create an __orc_rt_CWrapperFunctionResult by copying the given string, + * including the null-terminator. + * + * This function copies the input string. The client is responsible for freeing + * the ErrMsg arg. + */ +static inline __orc_rt_CWrapperFunctionResult +__orc_rt_CreateCWrapperFunctionResultFromString(const char *Source) { + return __orc_rt_CreateCWrapperFunctionResultFromRange(Source, + strlen(Source) + 1); +} + +/** + * Create an __orc_rt_CWrapperFunctionResult representing an out-of-band + * error. + * + * This function copies the input string. The client is responsible for freeing + * the ErrMsg arg. + */ +static inline __orc_rt_CWrapperFunctionResult +__orc_rt_CreateCWrapperFunctionResultFromOutOfBandError(const char *ErrMsg) { + __orc_rt_CWrapperFunctionResult R; + R.Size = 0; + char *Tmp = (char *)malloc(strlen(ErrMsg) + 1); + strcpy(Tmp, ErrMsg); + R.Data.ValuePtr = Tmp; + return R; +} + +/** + * This should be called to destroy __orc_rt_CWrapperFunctionResult values + * regardless of their state. + */ +static inline void +__orc_rt_DisposeCWrapperFunctionResult(__orc_rt_CWrapperFunctionResult *R) { + if (R->Size > sizeof(R->Data.Value) || + (R->Size == 0 && R->Data.ValuePtr)) + free(R->Data.ValuePtr); +} + +/** + * Get a pointer to the data contained in the given + * __orc_rt_CWrapperFunctionResult. + */ +static inline char * +__orc_rt_CWrapperFunctionResultData(__orc_rt_CWrapperFunctionResult *R) { + assert((R->Size != 0 || R->Data.ValuePtr == NULL) && + "Cannot get data for out-of-band error value"); + return R->Size > sizeof(R->Data.Value) ? R->Data.ValuePtr : R->Data.Value; +} + +/** + * Safely get the size of the given __orc_rt_CWrapperFunctionResult. + * + * Asserts that we're not trying to access the size of an error value. + */ +static inline size_t +__orc_rt_CWrapperFunctionResultSize(const __orc_rt_CWrapperFunctionResult *R) { + assert((R->Size != 0 || R->Data.ValuePtr == NULL) && + "Cannot get size for out-of-band error value"); + return R->Size; +} + +/** + * Returns 1 if this value is equivalent to a value just initialized by + * __orc_rt_CWrapperFunctionResultInit, 0 otherwise. + */ +static inline size_t +__orc_rt_CWrapperFunctionResultEmpty(const __orc_rt_CWrapperFunctionResult *R) { + return R->Size == 0 && R->Data.ValuePtr == 0; +} + +/** + * Returns a pointer to the out-of-band error string for this + * __orc_rt_CWrapperFunctionResult, or null if there is no error. + * + * The __orc_rt_CWrapperFunctionResult retains ownership of the error + * string, so it should be copied if the caller wishes to preserve it. + */ +static inline const char *__orc_rt_CWrapperFunctionResultGetOutOfBandError( + const __orc_rt_CWrapperFunctionResult *R) { + return R->Size == 0 ? R->Data.ValuePtr : 0; +} + +ORC_RT_C_EXTERN_C_END + +#endif /* ORC_RT_C_API_H */ diff --git a/gnu/llvm/compiler-rt/include/profile/InstrProfData.inc b/gnu/llvm/compiler-rt/include/profile/InstrProfData.inc index 7d2097cfc29..05419bf01f5 100644 --- a/gnu/llvm/compiler-rt/include/profile/InstrProfData.inc +++ b/gnu/llvm/compiler-rt/include/profile/InstrProfData.inc @@ -75,9 +75,7 @@ INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \ 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::getInt64PtrTy(Ctx), CounterPtr, \ - ConstantExpr::getBitCast(CounterPtr, \ - llvm::Type::getInt64PtrTy(Ctx))) +INSTR_PROF_DATA(const IntPtrT, IntPtrTy, CounterPtr, RelativeCounterPtr) /* This is used to map function pointers for the indirect call targets to * function name hashes during the conversion from raw to merged profile * data. @@ -130,12 +128,15 @@ INSTR_PROF_VALUE_NODE(PtrToNodeT, llvm::Type::getInt8PtrTy(Ctx), Next, \ 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, BinaryIdsSize, __llvm_write_binary_ids(NULL)) +/* FIXME: A more accurate name is NumData */ INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize) INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesBeforeCounters, PaddingBytesBeforeCounters) +/* FIXME: A more accurate name is NumCounters */ INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize) INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesAfterCounters, PaddingBytesAfterCounters) INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize) -INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin) +INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, + (uintptr_t)CountersBegin - (uintptr_t)DataBegin) INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin) INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last) #undef INSTR_PROF_RAW_HEADER @@ -645,24 +646,33 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \ (uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129 +/* FIXME: Please remedy the fixme in the header before bumping the version. */ /* Raw profile format version (start from 1). */ -#define INSTR_PROF_RAW_VERSION 7 +#define INSTR_PROF_RAW_VERSION 8 /* Indexed profile format version (start from 1). */ -#define INSTR_PROF_INDEX_VERSION 7 +#define INSTR_PROF_INDEX_VERSION 9 /* Coverage mapping format version (start from 0). */ #define INSTR_PROF_COVMAP_VERSION 5 /* Profile version is always of type uint64_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 + * bits (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentation * generated profile, and 0 if this is a Clang FE generated profile. * 1 in bit 57 indicates there are context-sensitive records in the profile. + * The 59th bit indicates whether to use debug info to correlate profiles. + * The 60th bit indicates single byte coverage instrumentation. + * The 61st bit indicates function entry instrumentation only. + * The 62nd bit indicates whether memory profile information is present. */ #define VARIANT_MASKS_ALL 0xff00000000000000ULL #define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL) #define VARIANT_MASK_IR_PROF (0x1ULL << 56) #define VARIANT_MASK_CSIR_PROF (0x1ULL << 57) #define VARIANT_MASK_INSTR_ENTRY (0x1ULL << 58) +#define VARIANT_MASK_DBG_CORRELATE (0x1ULL << 59) +#define VARIANT_MASK_BYTE_COVERAGE (0x1ULL << 60) +#define VARIANT_MASK_FUNCTION_ENTRY_ONLY (0x1ULL << 61) +#define VARIANT_MASK_MEMPROF (0x1ULL << 62) #define INSTR_PROF_RAW_VERSION_VAR __llvm_profile_raw_version #define INSTR_PROF_PROFILE_RUNTIME_VAR __llvm_profile_runtime #define INSTR_PROF_PROFILE_COUNTER_BIAS_VAR __llvm_profile_counter_bias diff --git a/gnu/llvm/compiler-rt/include/profile/MIBEntryDef.inc b/gnu/llvm/compiler-rt/include/profile/MIBEntryDef.inc new file mode 100644 index 00000000000..794163ae103 --- /dev/null +++ b/gnu/llvm/compiler-rt/include/profile/MIBEntryDef.inc @@ -0,0 +1,53 @@ +/*===-- MemEntryDef.inc - MemProf profiling runtime macros -*- C++ -*-======== *\ +|* +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +|* See https://llvm.org/LICENSE.txt for license information. +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +|* +\*===----------------------------------------------------------------------===*/ +/* + * This file defines the macros for memprof profiling data structures. + * Eg. usage to define the memprof meminfoblock struct: + * + * struct MemInfoBlock { + * #define MIBEntryDef(NameTag, Name, Type) Type Name; + * #include MIBEntryDef.inc + * #undef MIBEntryDef + * }; + * + * This file has two identical copies. The primary copy lives in LLVM and + * the other one sits in compiler-rt/include/profile directory. To make changes + * in this file, first modify the primary 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. + * +\*===----------------------------------------------------------------------===*/ +#ifndef MIBEntryDef +#define MIBEntryDef(NameTag, Name, Type) +#endif + +MIBEntryDef(AllocCount = 1, AllocCount, uint32_t) +MIBEntryDef(TotalAccessCount = 2, TotalAccessCount, uint64_t) +MIBEntryDef(MinAccessCount = 3, MinAccessCount, uint64_t) +MIBEntryDef(MaxAccessCount = 4, MaxAccessCount, uint64_t) +MIBEntryDef(TotalSize = 5, TotalSize, uint64_t) +MIBEntryDef(MinSize = 6, MinSize, uint32_t) +MIBEntryDef(MaxSize = 7, MaxSize, uint32_t) +MIBEntryDef(AllocTimestamp = 8, AllocTimestamp, uint32_t) +MIBEntryDef(DeallocTimestamp = 9, DeallocTimestamp, uint32_t) +MIBEntryDef(TotalLifetime = 10, TotalLifetime, uint64_t) +MIBEntryDef(MinLifetime = 11, MinLifetime, uint32_t) +MIBEntryDef(MaxLifetime = 12, MaxLifetime, uint32_t) +MIBEntryDef(AllocCpuId = 13, AllocCpuId, uint32_t) +MIBEntryDef(DeallocCpuId = 14, DeallocCpuId, uint32_t) +MIBEntryDef(NumMigratedCpu = 15, NumMigratedCpu, uint32_t) +MIBEntryDef(NumLifetimeOverlaps = 16, NumLifetimeOverlaps, uint32_t) +MIBEntryDef(NumSameAllocCpu = 17, NumSameAllocCpu, uint32_t) +MIBEntryDef(NumSameDeallocCpu = 18, NumSameDeallocCpu, uint32_t) +MIBEntryDef(DataTypeId = 19, DataTypeId, uint64_t) +MIBEntryDef(TotalAccessDensity = 20, TotalAccessDensity, uint64_t) +MIBEntryDef(MinAccessDensity = 21, MinAccessDensity, uint32_t) +MIBEntryDef(MaxAccessDensity = 22, MaxAccessDensity, uint32_t) +MIBEntryDef(TotalLifetimeAccessDensity = 23, TotalLifetimeAccessDensity, uint64_t) +MIBEntryDef(MinLifetimeAccessDensity = 24, MinLifetimeAccessDensity, uint32_t) +MIBEntryDef(MaxLifetimeAccessDensity = 25, MaxLifetimeAccessDensity, uint32_t) diff --git a/gnu/llvm/compiler-rt/include/profile/MemProfData.inc b/gnu/llvm/compiler-rt/include/profile/MemProfData.inc new file mode 100644 index 00000000000..c533073da75 --- /dev/null +++ b/gnu/llvm/compiler-rt/include/profile/MemProfData.inc @@ -0,0 +1,202 @@ +#ifndef MEMPROF_DATA_INC +#define MEMPROF_DATA_INC +/*===-- MemProfData.inc - MemProf profiling runtime structures -*- C++ -*-=== *\ +|* +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +|* See https://llvm.org/LICENSE.txt for license information. +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +|* +\*===----------------------------------------------------------------------===*/ +/* + * This is the main file that defines all the data structure, signature, + * constant literals that are shared across profiling runtime library, + * and host tools (reader/writer). + * + * This file has two identical copies. The primary copy lives in LLVM and + * the other one sits in compiler-rt/include/profile directory. To make changes + * in this file, first modify the primary 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. + * +\*===----------------------------------------------------------------------===*/ + +#ifdef _MSC_VER +#define PACKED(...) __pragma(pack(push,1)) __VA_ARGS__ __pragma(pack(pop)) +#else +#define PACKED(...) __VA_ARGS__ __attribute__((__packed__)) +#endif + +// A 64-bit magic number to uniquely identify the raw binary memprof profile file. +#define MEMPROF_RAW_MAGIC_64 \ + ((uint64_t)255 << 56 | (uint64_t)'m' << 48 | (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | \ + (uint64_t)'o' << 24 | (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129) + +// The version number of the raw binary format. +#define MEMPROF_RAW_VERSION 2ULL + +namespace llvm { +namespace memprof { +// A struct describing the header used for the raw binary memprof profile format. +PACKED(struct Header { + uint64_t Magic; + uint64_t Version; + uint64_t TotalSize; + uint64_t SegmentOffset; + uint64_t MIBOffset; + uint64_t StackOffset; +}); + + +// A struct describing the information necessary to describe a /proc/maps +// segment entry for a particular binary/library identified by its build id. +PACKED(struct SegmentEntry { + uint64_t Start; + uint64_t End; + uint64_t Offset; + // This field is unused until sanitizer procmaps support for build ids for + // Linux-Elf is implemented. + uint8_t BuildId[32] = {0}; + + SegmentEntry(uint64_t S, uint64_t E, uint64_t O) : + Start(S), End(E), Offset(O) {} + + SegmentEntry(const SegmentEntry& S) { + Start = S.Start; + End = S.End; + Offset = S.Offset; + } + + SegmentEntry& operator=(const SegmentEntry& S) { + Start = S.Start; + End = S.End; + Offset = S.Offset; + return *this; + } + + bool operator==(const SegmentEntry& S) const { + return Start == S.Start && + End == S.End && + Offset == S.Offset; + } +}); + +// Packed struct definition for MSVC. We can't use the PACKED macro defined in +// MemProfData.inc since it would mean we are embedding a directive (the +// #include for MIBEntryDef) into the macros which is undefined behaviour. +#ifdef _MSC_VER +__pragma(pack(push,1)) +#endif + +// A struct representing the heap allocation characteristics of a particular +// runtime context. This struct is shared between the compiler-rt runtime and +// the raw profile reader. The indexed format uses a separate, self-describing +// backwards compatible format. +struct MemInfoBlock{ + +#define MIBEntryDef(NameTag, Name, Type) Type Name; +#include "MIBEntryDef.inc" +#undef MIBEntryDef + +bool operator==(const MemInfoBlock& Other) const { + bool IsEqual = true; +#define MIBEntryDef(NameTag, Name, Type) \ + IsEqual = (IsEqual && Name == Other.Name); +#include "MIBEntryDef.inc" +#undef MIBEntryDef + return IsEqual; +} + +MemInfoBlock() { +#define MIBEntryDef(NameTag, Name, Type) Name = Type(); +#include "MIBEntryDef.inc" +#undef MIBEntryDef +} + +MemInfoBlock(uint32_t Size, uint64_t AccessCount, uint32_t AllocTs, + uint32_t DeallocTs, uint32_t AllocCpu, uint32_t DeallocCpu) + : MemInfoBlock() { + AllocCount = 1U; + TotalAccessCount = AccessCount; + MinAccessCount = AccessCount; + MaxAccessCount = AccessCount; + TotalSize = Size; + MinSize = Size; + MaxSize = Size; + AllocTimestamp = AllocTs; + DeallocTimestamp = DeallocTs; + TotalLifetime = DeallocTimestamp - AllocTimestamp; + MinLifetime = TotalLifetime; + MaxLifetime = TotalLifetime; + // Access density is accesses per byte. Multiply by 100 to include the + // fractional part. + TotalAccessDensity = AccessCount * 100 / Size; + MinAccessDensity = TotalAccessDensity; + MaxAccessDensity = TotalAccessDensity; + // Lifetime access density is the access density per second of lifetime. + // Multiply by 1000 to convert denominator lifetime to seconds (using a + // minimum lifetime of 1ms to avoid divide by 0. Do the multiplication first + // to reduce truncations to 0. + TotalLifetimeAccessDensity = + TotalAccessDensity * 1000 / (TotalLifetime ? TotalLifetime : 1); + MinLifetimeAccessDensity = TotalLifetimeAccessDensity; + MaxLifetimeAccessDensity = TotalLifetimeAccessDensity; + AllocCpuId = AllocCpu; + DeallocCpuId = DeallocCpu; + NumMigratedCpu = AllocCpuId != DeallocCpuId; +} + +void Merge(const MemInfoBlock &newMIB) { + AllocCount += newMIB.AllocCount; + + TotalAccessCount += newMIB.TotalAccessCount; + MinAccessCount = newMIB.MinAccessCount < MinAccessCount ? newMIB.MinAccessCount : MinAccessCount; + MaxAccessCount = newMIB.MaxAccessCount > MaxAccessCount ? newMIB.MaxAccessCount : MaxAccessCount; + + TotalSize += newMIB.TotalSize; + MinSize = newMIB.MinSize < MinSize ? newMIB.MinSize : MinSize; + MaxSize = newMIB.MaxSize > MaxSize ? newMIB.MaxSize : MaxSize; + + TotalLifetime += newMIB.TotalLifetime; + MinLifetime = newMIB.MinLifetime < MinLifetime ? newMIB.MinLifetime : MinLifetime; + MaxLifetime = newMIB.MaxLifetime > MaxLifetime ? newMIB.MaxLifetime : MaxLifetime; + + TotalAccessDensity += newMIB.TotalAccessDensity; + MinAccessDensity = newMIB.MinAccessDensity < MinAccessDensity + ? newMIB.MinAccessDensity + : MinAccessDensity; + MaxAccessDensity = newMIB.MaxAccessDensity > MaxAccessDensity + ? newMIB.MaxAccessDensity + : MaxAccessDensity; + + TotalLifetimeAccessDensity += newMIB.TotalLifetimeAccessDensity; + MinLifetimeAccessDensity = + newMIB.MinLifetimeAccessDensity < MinLifetimeAccessDensity + ? newMIB.MinLifetimeAccessDensity + : MinLifetimeAccessDensity; + MaxLifetimeAccessDensity = + newMIB.MaxLifetimeAccessDensity > MaxLifetimeAccessDensity + ? newMIB.MaxLifetimeAccessDensity + : MaxLifetimeAccessDensity; + + // We know newMIB was deallocated later, so just need to check if it was + // allocated before last one deallocated. + NumLifetimeOverlaps += newMIB.AllocTimestamp < DeallocTimestamp; + AllocTimestamp = newMIB.AllocTimestamp; + DeallocTimestamp = newMIB.DeallocTimestamp; + + NumSameAllocCpu += AllocCpuId == newMIB.AllocCpuId; + NumSameDeallocCpu += DeallocCpuId == newMIB.DeallocCpuId; + AllocCpuId = newMIB.AllocCpuId; + DeallocCpuId = newMIB.DeallocCpuId; +} + +#ifdef _MSC_VER +} __pragma(pack(pop)); +#else +} __attribute__((__packed__)); +#endif + +} // namespace memprof +} // namespace llvm + +#endif diff --git a/gnu/llvm/compiler-rt/include/sanitizer/asan_interface.h b/gnu/llvm/compiler-rt/include/sanitizer/asan_interface.h index 792ef9cfaa3..9bff21c117b 100644 --- a/gnu/llvm/compiler-rt/include/sanitizer/asan_interface.h +++ b/gnu/llvm/compiler-rt/include/sanitizer/asan_interface.h @@ -316,7 +316,7 @@ void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg, void __asan_handle_no_return(void); /// Update allocation stack trace for the given allocation to the current stack -/// trace. Returns 1 if successfull, 0 if not. +/// trace. Returns 1 if successful, 0 if not. int __asan_update_allocation_context(void* addr); #ifdef __cplusplus diff --git a/gnu/llvm/compiler-rt/include/sanitizer/common_interface_defs.h b/gnu/llvm/compiler-rt/include/sanitizer/common_interface_defs.h index cd69285b8d4..2f415bd9e85 100644 --- a/gnu/llvm/compiler-rt/include/sanitizer/common_interface_defs.h +++ b/gnu/llvm/compiler-rt/include/sanitizer/common_interface_defs.h @@ -28,7 +28,7 @@ typedef struct { // Enable sandbox support in sanitizer coverage. int coverage_sandboxed; // File descriptor to write coverage data to. If -1 is passed, a file will - // be pre-opened by __sanitizer_sandobx_on_notify(). This field has no + // be pre-opened by __sanitizer_sandbox_on_notify(). This field has no // effect if coverage_sandboxed == 0. intptr_t coverage_fd; // If non-zero, split the coverage data into well-formed blocks. This is @@ -159,6 +159,40 @@ void __sanitizer_annotate_contiguous_container(const void *beg, const void *old_mid, const void *new_mid); +/// Similar to __sanitizer_annotate_contiguous_container. +/// +/// Annotates the current state of a contiguous container memory, +/// such as std::deque's single chunk, when the boundries are moved. +/// +/// A contiguous chunk is a chunk that keeps all of its elements +/// in a contiguous region of memory. The container owns the region of memory +/// [storage_beg, storage_end); the memory [container_beg, +/// container_end) is used to store the current elements, and the memory +/// [storage_beg, container_beg), [container_end, storage_end) is +/// reserved for future elements (storage_beg <= container_beg <= +/// container_end <= storage_end). For example, in std::deque : +/// - chunk with a frist deques element will have container_beg equal to address +/// of the first element. +/// - in every next chunk with elements, true is container_beg == +/// storage_beg . +/// +/// Argument requirements: +/// During unpoisoning memory of empty container (before first element is +/// added): +/// - old_container_beg_p == old_container_end_p +/// During poisoning after last element was removed: +/// - new_container_beg_p == new_container_end_p +/// \param storage_beg Beginning of memory region. +/// \param storage_end End of memory region. +/// \param old_container_beg Old beginning of used region. +/// \param old_container_end End of used region. +/// \param new_container_beg New beginning of used region. +/// \param new_container_end New end of used region. +void __sanitizer_annotate_double_ended_contiguous_container( + const void *storage_beg, const void *storage_end, + const void *old_container_beg, const void *old_container_end, + const void *new_container_beg, const void *new_container_end); + /// Returns true if the contiguous container [beg, end) is properly /// poisoned. /// @@ -178,6 +212,31 @@ void __sanitizer_annotate_contiguous_container(const void *beg, int __sanitizer_verify_contiguous_container(const void *beg, const void *mid, const void *end); +/// Returns true if the double ended contiguous +/// container [storage_beg, storage_end) is properly poisoned. +/// +/// Proper poisoning could occur, for example, with +/// __sanitizer_annotate_double_ended_contiguous_container), that is, if +/// [storage_beg, container_beg) is not addressable, [container_beg, +/// container_end) is addressable and [container_end, end) is +/// unaddressable. Full verification requires O (storage_end - +/// storage_beg) time; this function tries to avoid such complexity by +/// touching only parts of the container around storage_beg, +/// container_beg, container_end, and +/// storage_end. +/// +/// \param storage_beg Beginning of memory region. +/// \param container_beg Beginning of used region. +/// \param container_end End of used region. +/// \param storage_end End of memory region. +/// +/// \returns True if the double-ended contiguous container [storage_beg, +/// container_beg, container_end, end) is properly poisoned - only +/// [container_beg; container_end) is addressable. +int __sanitizer_verify_double_ended_contiguous_container( + const void *storage_beg, const void *container_beg, + const void *container_end, const void *storage_end); + /// Similar to __sanitizer_verify_contiguous_container() but also /// returns the address of the first improperly poisoned byte. /// @@ -192,6 +251,20 @@ const void *__sanitizer_contiguous_container_find_bad_address(const void *beg, const void *mid, const void *end); +/// returns the address of the first improperly poisoned byte. +/// +/// Returns NULL if the area is poisoned properly. +/// +/// \param storage_beg Beginning of memory region. +/// \param container_beg Beginning of used region. +/// \param container_end End of used region. +/// \param storage_end End of memory region. +/// +/// \returns The bad address or NULL. +const void *__sanitizer_double_ended_contiguous_container_find_bad_address( + const void *storage_beg, const void *container_beg, + const void *container_end, const void *storage_end); + /// Prints the stack trace leading to this call (useful for calling from the /// debugger). void __sanitizer_print_stack_trace(void); @@ -211,6 +284,15 @@ void __sanitizer_symbolize_pc(void *pc, const char *fmt, char *out_buf, // Same as __sanitizer_symbolize_pc, but for data section (i.e. globals). void __sanitizer_symbolize_global(void *data_ptr, const char *fmt, char *out_buf, size_t out_buf_size); +// Determine the return address. +#if !defined(_MSC_VER) || defined(__clang__) +#define __sanitizer_return_address() \ + __builtin_extract_return_addr(__builtin_return_address(0)) +#else +extern "C" void *_ReturnAddress(void); +#pragma intrinsic(_ReturnAddress) +#define __sanitizer_return_address() _ReturnAddress() +#endif /// Sets the callback to be called immediately before death on error. /// diff --git a/gnu/llvm/compiler-rt/include/sanitizer/dfsan_interface.h b/gnu/llvm/compiler-rt/include/sanitizer/dfsan_interface.h index cd3b6d6e2b1..519bfffa9a2 100644 --- a/gnu/llvm/compiler-rt/include/sanitizer/dfsan_interface.h +++ b/gnu/llvm/compiler-rt/include/sanitizer/dfsan_interface.h @@ -27,6 +27,18 @@ typedef uint32_t dfsan_origin; /// Signature of the callback argument to dfsan_set_write_callback(). typedef void (*dfsan_write_callback_t)(int fd, const void *buf, size_t count); +/// Signature of the callback argument to dfsan_set_conditional_callback(). +typedef void (*dfsan_conditional_callback_t)(dfsan_label label, + dfsan_origin origin); + +/// Signature of the callback argument to dfsan_set_reaches_function_callback(). +/// The description is intended to hold the name of the variable. +typedef void (*dfsan_reaches_function_callback_t)(dfsan_label label, + dfsan_origin origin, + const char *file, + unsigned int line, + const char *function); + /// Computes the union of \c l1 and \c l2, resulting in a union label. dfsan_label dfsan_union(dfsan_label l1, dfsan_label l2); @@ -54,6 +66,10 @@ dfsan_origin dfsan_get_origin(long data); /// Retrieves the label associated with the data at the given address. dfsan_label dfsan_read_label(const void *addr, size_t size); +/// Return the origin associated with the first taint byte in the size bytes +/// from the address addr. +dfsan_origin dfsan_read_origin_of_first_taint(const void *addr, size_t size); + /// Returns whether the given label label contains the label elem. int dfsan_has_label(dfsan_label label, dfsan_label elem); @@ -70,6 +86,31 @@ void dfsan_flush(void); /// callback executes. Pass in NULL to remove any callback. void dfsan_set_write_callback(dfsan_write_callback_t labeled_write_callback); +/// Sets a callback to be invoked on any conditional expressions which have a +/// taint label set. This can be used to find where tainted data influences +/// the behavior of the program. +/// These callbacks will only be added when -dfsan-conditional-callbacks=true. +void dfsan_set_conditional_callback(dfsan_conditional_callback_t callback); + +/// Conditional expressions occur during signal handlers. +/// Making callbacks that handle signals well is tricky, so when +/// -dfsan-conditional-callbacks=true, conditional expressions used in signal +/// handlers will add the labels they see into a global (bitwise-or together). +/// This function returns all label bits seen in signal handler conditions. +dfsan_label dfsan_get_labels_in_signal_conditional(); + +/// Sets a callback to be invoked when tainted data reaches a function. +/// This could occur at function entry, or at a load instruction. +/// These callbacks will only be added if -dfsan-reaches-function-callbacks=1. +void dfsan_set_reaches_function_callback( + dfsan_reaches_function_callback_t callback); + +/// Making callbacks that handle signals well is tricky, so when +/// -dfsan-reaches-function-callbacks=true, functions reached in signal +/// handlers will add the labels they see into a global (bitwise-or together). +/// This function returns all label bits seen during signal handlers. +dfsan_label dfsan_get_labels_in_signal_reaches_function(); + /// Interceptor hooks. /// Whenever a dfsan's custom function is called the corresponding /// hook is called it non-zero. The hooks should be defined by the user. @@ -87,6 +128,9 @@ void dfsan_weak_hook_strncmp(void *caller_pc, const char *s1, const char *s2, /// prints description at the beginning of the trace. If origin tracking is not /// on, or the address is not labeled, it prints nothing. void dfsan_print_origin_trace(const void *addr, const char *description); +/// As above, but use an origin id from dfsan_get_origin() instead of address. +/// Does not include header line with taint label and address information. +void dfsan_print_origin_id_trace(dfsan_origin origin); /// Prints the origin trace of the label at the address \p addr to a /// pre-allocated output buffer. If origin tracking is not on, or the address is @@ -124,6 +168,10 @@ void dfsan_print_origin_trace(const void *addr, const char *description); /// return value is not less than \p out_buf_size. size_t dfsan_sprint_origin_trace(const void *addr, const char *description, char *out_buf, size_t out_buf_size); +/// As above, but use an origin id from dfsan_get_origin() instead of address. +/// Does not include header line with taint label and address information. +size_t dfsan_sprint_origin_id_trace(dfsan_origin origin, char *out_buf, + size_t out_buf_size); /// Prints the stack trace leading to this call to a pre-allocated output /// buffer. @@ -150,8 +198,7 @@ int dfsan_get_track_origins(void); #ifdef __cplusplus } // extern "C" -template -void dfsan_set_label(dfsan_label label, T &data) { // NOLINT +template void dfsan_set_label(dfsan_label label, T &data) { dfsan_set_label(label, (void *)&data, sizeof(T)); } diff --git a/gnu/llvm/compiler-rt/include/sanitizer/linux_syscall_hooks.h b/gnu/llvm/compiler-rt/include/sanitizer/linux_syscall_hooks.h index 56eae3d40f9..3f3f1e78dfb 100644 --- a/gnu/llvm/compiler-rt/include/sanitizer/linux_syscall_hooks.h +++ b/gnu/llvm/compiler-rt/include/sanitizer/linux_syscall_hooks.h @@ -20,1493 +20,1502 @@ #ifndef SANITIZER_LINUX_SYSCALL_HOOKS_H #define SANITIZER_LINUX_SYSCALL_HOOKS_H -#define __sanitizer_syscall_pre_time(tloc) \ +#define __sanitizer_syscall_pre_time(tloc) \ __sanitizer_syscall_pre_impl_time((long)(tloc)) -#define __sanitizer_syscall_post_time(res, tloc) \ +#define __sanitizer_syscall_post_time(res, tloc) \ __sanitizer_syscall_post_impl_time(res, (long)(tloc)) -#define __sanitizer_syscall_pre_stime(tptr) \ +#define __sanitizer_syscall_pre_stime(tptr) \ __sanitizer_syscall_pre_impl_stime((long)(tptr)) -#define __sanitizer_syscall_post_stime(res, tptr) \ +#define __sanitizer_syscall_post_stime(res, tptr) \ __sanitizer_syscall_post_impl_stime(res, (long)(tptr)) -#define __sanitizer_syscall_pre_gettimeofday(tv, tz) \ +#define __sanitizer_syscall_pre_gettimeofday(tv, tz) \ __sanitizer_syscall_pre_impl_gettimeofday((long)(tv), (long)(tz)) -#define __sanitizer_syscall_post_gettimeofday(res, tv, tz) \ +#define __sanitizer_syscall_post_gettimeofday(res, tv, tz) \ __sanitizer_syscall_post_impl_gettimeofday(res, (long)(tv), (long)(tz)) -#define __sanitizer_syscall_pre_settimeofday(tv, tz) \ +#define __sanitizer_syscall_pre_settimeofday(tv, tz) \ __sanitizer_syscall_pre_impl_settimeofday((long)(tv), (long)(tz)) -#define __sanitizer_syscall_post_settimeofday(res, tv, tz) \ +#define __sanitizer_syscall_post_settimeofday(res, tv, tz) \ __sanitizer_syscall_post_impl_settimeofday(res, (long)(tv), (long)(tz)) -#define __sanitizer_syscall_pre_adjtimex(txc_p) \ +#define __sanitizer_syscall_pre_adjtimex(txc_p) \ __sanitizer_syscall_pre_impl_adjtimex((long)(txc_p)) -#define __sanitizer_syscall_post_adjtimex(res, txc_p) \ +#define __sanitizer_syscall_post_adjtimex(res, txc_p) \ __sanitizer_syscall_post_impl_adjtimex(res, (long)(txc_p)) -#define __sanitizer_syscall_pre_times(tbuf) \ +#define __sanitizer_syscall_pre_times(tbuf) \ __sanitizer_syscall_pre_impl_times((long)(tbuf)) -#define __sanitizer_syscall_post_times(res, tbuf) \ +#define __sanitizer_syscall_post_times(res, tbuf) \ __sanitizer_syscall_post_impl_times(res, (long)(tbuf)) #define __sanitizer_syscall_pre_gettid() __sanitizer_syscall_pre_impl_gettid() -#define __sanitizer_syscall_post_gettid(res) \ +#define __sanitizer_syscall_post_gettid(res) \ __sanitizer_syscall_post_impl_gettid(res) -#define __sanitizer_syscall_pre_nanosleep(rqtp, rmtp) \ +#define __sanitizer_syscall_pre_nanosleep(rqtp, rmtp) \ __sanitizer_syscall_pre_impl_nanosleep((long)(rqtp), (long)(rmtp)) -#define __sanitizer_syscall_post_nanosleep(res, rqtp, rmtp) \ +#define __sanitizer_syscall_post_nanosleep(res, rqtp, rmtp) \ __sanitizer_syscall_post_impl_nanosleep(res, (long)(rqtp), (long)(rmtp)) -#define __sanitizer_syscall_pre_alarm(seconds) \ +#define __sanitizer_syscall_pre_alarm(seconds) \ __sanitizer_syscall_pre_impl_alarm((long)(seconds)) -#define __sanitizer_syscall_post_alarm(res, seconds) \ +#define __sanitizer_syscall_post_alarm(res, seconds) \ __sanitizer_syscall_post_impl_alarm(res, (long)(seconds)) #define __sanitizer_syscall_pre_getpid() __sanitizer_syscall_pre_impl_getpid() -#define __sanitizer_syscall_post_getpid(res) \ +#define __sanitizer_syscall_post_getpid(res) \ __sanitizer_syscall_post_impl_getpid(res) #define __sanitizer_syscall_pre_getppid() __sanitizer_syscall_pre_impl_getppid() -#define __sanitizer_syscall_post_getppid(res) \ +#define __sanitizer_syscall_post_getppid(res) \ __sanitizer_syscall_post_impl_getppid(res) #define __sanitizer_syscall_pre_getuid() __sanitizer_syscall_pre_impl_getuid() -#define __sanitizer_syscall_post_getuid(res) \ +#define __sanitizer_syscall_post_getuid(res) \ __sanitizer_syscall_post_impl_getuid(res) #define __sanitizer_syscall_pre_geteuid() __sanitizer_syscall_pre_impl_geteuid() -#define __sanitizer_syscall_post_geteuid(res) \ +#define __sanitizer_syscall_post_geteuid(res) \ __sanitizer_syscall_post_impl_geteuid(res) #define __sanitizer_syscall_pre_getgid() __sanitizer_syscall_pre_impl_getgid() -#define __sanitizer_syscall_post_getgid(res) \ +#define __sanitizer_syscall_post_getgid(res) \ __sanitizer_syscall_post_impl_getgid(res) #define __sanitizer_syscall_pre_getegid() __sanitizer_syscall_pre_impl_getegid() -#define __sanitizer_syscall_post_getegid(res) \ +#define __sanitizer_syscall_post_getegid(res) \ __sanitizer_syscall_post_impl_getegid(res) -#define __sanitizer_syscall_pre_getresuid(ruid, euid, suid) \ - __sanitizer_syscall_pre_impl_getresuid((long)(ruid), (long)(euid), \ +#define __sanitizer_syscall_pre_getresuid(ruid, euid, suid) \ + __sanitizer_syscall_pre_impl_getresuid((long)(ruid), (long)(euid), \ (long)(suid)) -#define __sanitizer_syscall_post_getresuid(res, ruid, euid, suid) \ - __sanitizer_syscall_post_impl_getresuid(res, (long)(ruid), (long)(euid), \ +#define __sanitizer_syscall_post_getresuid(res, ruid, euid, suid) \ + __sanitizer_syscall_post_impl_getresuid(res, (long)(ruid), (long)(euid), \ (long)(suid)) -#define __sanitizer_syscall_pre_getresgid(rgid, egid, sgid) \ - __sanitizer_syscall_pre_impl_getresgid((long)(rgid), (long)(egid), \ +#define __sanitizer_syscall_pre_getresgid(rgid, egid, sgid) \ + __sanitizer_syscall_pre_impl_getresgid((long)(rgid), (long)(egid), \ (long)(sgid)) -#define __sanitizer_syscall_post_getresgid(res, rgid, egid, sgid) \ - __sanitizer_syscall_post_impl_getresgid(res, (long)(rgid), (long)(egid), \ +#define __sanitizer_syscall_post_getresgid(res, rgid, egid, sgid) \ + __sanitizer_syscall_post_impl_getresgid(res, (long)(rgid), (long)(egid), \ (long)(sgid)) -#define __sanitizer_syscall_pre_getpgid(pid) \ +#define __sanitizer_syscall_pre_getpgid(pid) \ __sanitizer_syscall_pre_impl_getpgid((long)(pid)) -#define __sanitizer_syscall_post_getpgid(res, pid) \ +#define __sanitizer_syscall_post_getpgid(res, pid) \ __sanitizer_syscall_post_impl_getpgid(res, (long)(pid)) #define __sanitizer_syscall_pre_getpgrp() __sanitizer_syscall_pre_impl_getpgrp() -#define __sanitizer_syscall_post_getpgrp(res) \ +#define __sanitizer_syscall_post_getpgrp(res) \ __sanitizer_syscall_post_impl_getpgrp(res) -#define __sanitizer_syscall_pre_getsid(pid) \ +#define __sanitizer_syscall_pre_getsid(pid) \ __sanitizer_syscall_pre_impl_getsid((long)(pid)) -#define __sanitizer_syscall_post_getsid(res, pid) \ +#define __sanitizer_syscall_post_getsid(res, pid) \ __sanitizer_syscall_post_impl_getsid(res, (long)(pid)) -#define __sanitizer_syscall_pre_getgroups(gidsetsize, grouplist) \ +#define __sanitizer_syscall_pre_getgroups(gidsetsize, grouplist) \ __sanitizer_syscall_pre_impl_getgroups((long)(gidsetsize), (long)(grouplist)) -#define __sanitizer_syscall_post_getgroups(res, gidsetsize, grouplist) \ - __sanitizer_syscall_post_impl_getgroups(res, (long)(gidsetsize), \ +#define __sanitizer_syscall_post_getgroups(res, gidsetsize, grouplist) \ + __sanitizer_syscall_post_impl_getgroups(res, (long)(gidsetsize), \ (long)(grouplist)) -#define __sanitizer_syscall_pre_setregid(rgid, egid) \ +#define __sanitizer_syscall_pre_setregid(rgid, egid) \ __sanitizer_syscall_pre_impl_setregid((long)(rgid), (long)(egid)) -#define __sanitizer_syscall_post_setregid(res, rgid, egid) \ +#define __sanitizer_syscall_post_setregid(res, rgid, egid) \ __sanitizer_syscall_post_impl_setregid(res, (long)(rgid), (long)(egid)) -#define __sanitizer_syscall_pre_setgid(gid) \ +#define __sanitizer_syscall_pre_setgid(gid) \ __sanitizer_syscall_pre_impl_setgid((long)(gid)) -#define __sanitizer_syscall_post_setgid(res, gid) \ +#define __sanitizer_syscall_post_setgid(res, gid) \ __sanitizer_syscall_post_impl_setgid(res, (long)(gid)) -#define __sanitizer_syscall_pre_setreuid(ruid, euid) \ +#define __sanitizer_syscall_pre_setreuid(ruid, euid) \ __sanitizer_syscall_pre_impl_setreuid((long)(ruid), (long)(euid)) -#define __sanitizer_syscall_post_setreuid(res, ruid, euid) \ +#define __sanitizer_syscall_post_setreuid(res, ruid, euid) \ __sanitizer_syscall_post_impl_setreuid(res, (long)(ruid), (long)(euid)) -#define __sanitizer_syscall_pre_setuid(uid) \ +#define __sanitizer_syscall_pre_setuid(uid) \ __sanitizer_syscall_pre_impl_setuid((long)(uid)) -#define __sanitizer_syscall_post_setuid(res, uid) \ +#define __sanitizer_syscall_post_setuid(res, uid) \ __sanitizer_syscall_post_impl_setuid(res, (long)(uid)) -#define __sanitizer_syscall_pre_setresuid(ruid, euid, suid) \ - __sanitizer_syscall_pre_impl_setresuid((long)(ruid), (long)(euid), \ +#define __sanitizer_syscall_pre_setresuid(ruid, euid, suid) \ + __sanitizer_syscall_pre_impl_setresuid((long)(ruid), (long)(euid), \ (long)(suid)) -#define __sanitizer_syscall_post_setresuid(res, ruid, euid, suid) \ - __sanitizer_syscall_post_impl_setresuid(res, (long)(ruid), (long)(euid), \ +#define __sanitizer_syscall_post_setresuid(res, ruid, euid, suid) \ + __sanitizer_syscall_post_impl_setresuid(res, (long)(ruid), (long)(euid), \ (long)(suid)) -#define __sanitizer_syscall_pre_setresgid(rgid, egid, sgid) \ - __sanitizer_syscall_pre_impl_setresgid((long)(rgid), (long)(egid), \ +#define __sanitizer_syscall_pre_setresgid(rgid, egid, sgid) \ + __sanitizer_syscall_pre_impl_setresgid((long)(rgid), (long)(egid), \ (long)(sgid)) -#define __sanitizer_syscall_post_setresgid(res, rgid, egid, sgid) \ - __sanitizer_syscall_post_impl_setresgid(res, (long)(rgid), (long)(egid), \ +#define __sanitizer_syscall_post_setresgid(res, rgid, egid, sgid) \ + __sanitizer_syscall_post_impl_setresgid(res, (long)(rgid), (long)(egid), \ (long)(sgid)) -#define __sanitizer_syscall_pre_setfsuid(uid) \ +#define __sanitizer_syscall_pre_setfsuid(uid) \ __sanitizer_syscall_pre_impl_setfsuid((long)(uid)) -#define __sanitizer_syscall_post_setfsuid(res, uid) \ +#define __sanitizer_syscall_post_setfsuid(res, uid) \ __sanitizer_syscall_post_impl_setfsuid(res, (long)(uid)) -#define __sanitizer_syscall_pre_setfsgid(gid) \ +#define __sanitizer_syscall_pre_setfsgid(gid) \ __sanitizer_syscall_pre_impl_setfsgid((long)(gid)) -#define __sanitizer_syscall_post_setfsgid(res, gid) \ +#define __sanitizer_syscall_post_setfsgid(res, gid) \ __sanitizer_syscall_post_impl_setfsgid(res, (long)(gid)) -#define __sanitizer_syscall_pre_setpgid(pid, pgid) \ +#define __sanitizer_syscall_pre_setpgid(pid, pgid) \ __sanitizer_syscall_pre_impl_setpgid((long)(pid), (long)(pgid)) -#define __sanitizer_syscall_post_setpgid(res, pid, pgid) \ +#define __sanitizer_syscall_post_setpgid(res, pid, pgid) \ __sanitizer_syscall_post_impl_setpgid(res, (long)(pid), (long)(pgid)) #define __sanitizer_syscall_pre_setsid() __sanitizer_syscall_pre_impl_setsid() -#define __sanitizer_syscall_post_setsid(res) \ +#define __sanitizer_syscall_post_setsid(res) \ __sanitizer_syscall_post_impl_setsid(res) -#define __sanitizer_syscall_pre_setgroups(gidsetsize, grouplist) \ +#define __sanitizer_syscall_pre_setgroups(gidsetsize, grouplist) \ __sanitizer_syscall_pre_impl_setgroups((long)(gidsetsize), (long)(grouplist)) -#define __sanitizer_syscall_post_setgroups(res, gidsetsize, grouplist) \ - __sanitizer_syscall_post_impl_setgroups(res, (long)(gidsetsize), \ +#define __sanitizer_syscall_post_setgroups(res, gidsetsize, grouplist) \ + __sanitizer_syscall_post_impl_setgroups(res, (long)(gidsetsize), \ (long)(grouplist)) -#define __sanitizer_syscall_pre_acct(name) \ +#define __sanitizer_syscall_pre_acct(name) \ __sanitizer_syscall_pre_impl_acct((long)(name)) -#define __sanitizer_syscall_post_acct(res, name) \ +#define __sanitizer_syscall_post_acct(res, name) \ __sanitizer_syscall_post_impl_acct(res, (long)(name)) -#define __sanitizer_syscall_pre_capget(header, dataptr) \ +#define __sanitizer_syscall_pre_capget(header, dataptr) \ __sanitizer_syscall_pre_impl_capget((long)(header), (long)(dataptr)) -#define __sanitizer_syscall_post_capget(res, header, dataptr) \ +#define __sanitizer_syscall_post_capget(res, header, dataptr) \ __sanitizer_syscall_post_impl_capget(res, (long)(header), (long)(dataptr)) -#define __sanitizer_syscall_pre_capset(header, data) \ +#define __sanitizer_syscall_pre_capset(header, data) \ __sanitizer_syscall_pre_impl_capset((long)(header), (long)(data)) -#define __sanitizer_syscall_post_capset(res, header, data) \ +#define __sanitizer_syscall_post_capset(res, header, data) \ __sanitizer_syscall_post_impl_capset(res, (long)(header), (long)(data)) -#define __sanitizer_syscall_pre_personality(personality) \ +#define __sanitizer_syscall_pre_personality(personality) \ __sanitizer_syscall_pre_impl_personality((long)(personality)) -#define __sanitizer_syscall_post_personality(res, personality) \ +#define __sanitizer_syscall_post_personality(res, personality) \ __sanitizer_syscall_post_impl_personality(res, (long)(personality)) -#define __sanitizer_syscall_pre_sigpending(set) \ +#define __sanitizer_syscall_pre_sigpending(set) \ __sanitizer_syscall_pre_impl_sigpending((long)(set)) -#define __sanitizer_syscall_post_sigpending(res, set) \ +#define __sanitizer_syscall_post_sigpending(res, set) \ __sanitizer_syscall_post_impl_sigpending(res, (long)(set)) -#define __sanitizer_syscall_pre_sigprocmask(how, set, oset) \ - __sanitizer_syscall_pre_impl_sigprocmask((long)(how), (long)(set), \ +#define __sanitizer_syscall_pre_sigprocmask(how, set, oset) \ + __sanitizer_syscall_pre_impl_sigprocmask((long)(how), (long)(set), \ (long)(oset)) -#define __sanitizer_syscall_post_sigprocmask(res, how, set, oset) \ - __sanitizer_syscall_post_impl_sigprocmask(res, (long)(how), (long)(set), \ +#define __sanitizer_syscall_post_sigprocmask(res, how, set, oset) \ + __sanitizer_syscall_post_impl_sigprocmask(res, (long)(how), (long)(set), \ (long)(oset)) -#define __sanitizer_syscall_pre_getitimer(which, value) \ +#define __sanitizer_syscall_pre_getitimer(which, value) \ __sanitizer_syscall_pre_impl_getitimer((long)(which), (long)(value)) -#define __sanitizer_syscall_post_getitimer(res, which, value) \ +#define __sanitizer_syscall_post_getitimer(res, which, value) \ __sanitizer_syscall_post_impl_getitimer(res, (long)(which), (long)(value)) -#define __sanitizer_syscall_pre_setitimer(which, value, ovalue) \ - __sanitizer_syscall_pre_impl_setitimer((long)(which), (long)(value), \ +#define __sanitizer_syscall_pre_setitimer(which, value, ovalue) \ + __sanitizer_syscall_pre_impl_setitimer((long)(which), (long)(value), \ (long)(ovalue)) -#define __sanitizer_syscall_post_setitimer(res, which, value, ovalue) \ - __sanitizer_syscall_post_impl_setitimer(res, (long)(which), (long)(value), \ +#define __sanitizer_syscall_post_setitimer(res, which, value, ovalue) \ + __sanitizer_syscall_post_impl_setitimer(res, (long)(which), (long)(value), \ (long)(ovalue)) -#define __sanitizer_syscall_pre_timer_create(which_clock, timer_event_spec, \ - created_timer_id) \ - __sanitizer_syscall_pre_impl_timer_create( \ +#define __sanitizer_syscall_pre_timer_create(which_clock, timer_event_spec, \ + created_timer_id) \ + __sanitizer_syscall_pre_impl_timer_create( \ (long)(which_clock), (long)(timer_event_spec), (long)(created_timer_id)) -#define __sanitizer_syscall_post_timer_create( \ - res, which_clock, timer_event_spec, created_timer_id) \ - __sanitizer_syscall_post_impl_timer_create(res, (long)(which_clock), \ - (long)(timer_event_spec), \ +#define __sanitizer_syscall_post_timer_create( \ + res, which_clock, timer_event_spec, created_timer_id) \ + __sanitizer_syscall_post_impl_timer_create(res, (long)(which_clock), \ + (long)(timer_event_spec), \ (long)(created_timer_id)) -#define __sanitizer_syscall_pre_timer_gettime(timer_id, setting) \ +#define __sanitizer_syscall_pre_timer_gettime(timer_id, setting) \ __sanitizer_syscall_pre_impl_timer_gettime((long)(timer_id), (long)(setting)) -#define __sanitizer_syscall_post_timer_gettime(res, timer_id, setting) \ - __sanitizer_syscall_post_impl_timer_gettime(res, (long)(timer_id), \ +#define __sanitizer_syscall_post_timer_gettime(res, timer_id, setting) \ + __sanitizer_syscall_post_impl_timer_gettime(res, (long)(timer_id), \ (long)(setting)) -#define __sanitizer_syscall_pre_timer_getoverrun(timer_id) \ +#define __sanitizer_syscall_pre_timer_getoverrun(timer_id) \ __sanitizer_syscall_pre_impl_timer_getoverrun((long)(timer_id)) -#define __sanitizer_syscall_post_timer_getoverrun(res, timer_id) \ +#define __sanitizer_syscall_post_timer_getoverrun(res, timer_id) \ __sanitizer_syscall_post_impl_timer_getoverrun(res, (long)(timer_id)) -#define __sanitizer_syscall_pre_timer_settime(timer_id, flags, new_setting, \ - old_setting) \ - __sanitizer_syscall_pre_impl_timer_settime((long)(timer_id), (long)(flags), \ - (long)(new_setting), \ +#define __sanitizer_syscall_pre_timer_settime(timer_id, flags, new_setting, \ + old_setting) \ + __sanitizer_syscall_pre_impl_timer_settime((long)(timer_id), (long)(flags), \ + (long)(new_setting), \ (long)(old_setting)) -#define __sanitizer_syscall_post_timer_settime(res, timer_id, flags, \ - new_setting, old_setting) \ - __sanitizer_syscall_post_impl_timer_settime( \ - res, (long)(timer_id), (long)(flags), (long)(new_setting), \ +#define __sanitizer_syscall_post_timer_settime(res, timer_id, flags, \ + new_setting, old_setting) \ + __sanitizer_syscall_post_impl_timer_settime( \ + res, (long)(timer_id), (long)(flags), (long)(new_setting), \ (long)(old_setting)) -#define __sanitizer_syscall_pre_timer_delete(timer_id) \ +#define __sanitizer_syscall_pre_timer_delete(timer_id) \ __sanitizer_syscall_pre_impl_timer_delete((long)(timer_id)) -#define __sanitizer_syscall_post_timer_delete(res, timer_id) \ +#define __sanitizer_syscall_post_timer_delete(res, timer_id) \ __sanitizer_syscall_post_impl_timer_delete(res, (long)(timer_id)) -#define __sanitizer_syscall_pre_clock_settime(which_clock, tp) \ +#define __sanitizer_syscall_pre_clock_settime(which_clock, tp) \ __sanitizer_syscall_pre_impl_clock_settime((long)(which_clock), (long)(tp)) -#define __sanitizer_syscall_post_clock_settime(res, which_clock, tp) \ - __sanitizer_syscall_post_impl_clock_settime(res, (long)(which_clock), \ +#define __sanitizer_syscall_post_clock_settime(res, which_clock, tp) \ + __sanitizer_syscall_post_impl_clock_settime(res, (long)(which_clock), \ (long)(tp)) -#define __sanitizer_syscall_pre_clock_gettime(which_clock, tp) \ +#define __sanitizer_syscall_pre_clock_gettime(which_clock, tp) \ __sanitizer_syscall_pre_impl_clock_gettime((long)(which_clock), (long)(tp)) -#define __sanitizer_syscall_post_clock_gettime(res, which_clock, tp) \ - __sanitizer_syscall_post_impl_clock_gettime(res, (long)(which_clock), \ +#define __sanitizer_syscall_post_clock_gettime(res, which_clock, tp) \ + __sanitizer_syscall_post_impl_clock_gettime(res, (long)(which_clock), \ (long)(tp)) -#define __sanitizer_syscall_pre_clock_adjtime(which_clock, tx) \ +#define __sanitizer_syscall_pre_clock_adjtime(which_clock, tx) \ __sanitizer_syscall_pre_impl_clock_adjtime((long)(which_clock), (long)(tx)) -#define __sanitizer_syscall_post_clock_adjtime(res, which_clock, tx) \ - __sanitizer_syscall_post_impl_clock_adjtime(res, (long)(which_clock), \ +#define __sanitizer_syscall_post_clock_adjtime(res, which_clock, tx) \ + __sanitizer_syscall_post_impl_clock_adjtime(res, (long)(which_clock), \ (long)(tx)) -#define __sanitizer_syscall_pre_clock_getres(which_clock, tp) \ +#define __sanitizer_syscall_pre_clock_getres(which_clock, tp) \ __sanitizer_syscall_pre_impl_clock_getres((long)(which_clock), (long)(tp)) -#define __sanitizer_syscall_post_clock_getres(res, which_clock, tp) \ - __sanitizer_syscall_post_impl_clock_getres(res, (long)(which_clock), \ +#define __sanitizer_syscall_post_clock_getres(res, which_clock, tp) \ + __sanitizer_syscall_post_impl_clock_getres(res, (long)(which_clock), \ (long)(tp)) -#define __sanitizer_syscall_pre_clock_nanosleep(which_clock, flags, rqtp, \ - rmtp) \ - __sanitizer_syscall_pre_impl_clock_nanosleep( \ +#define __sanitizer_syscall_pre_clock_nanosleep(which_clock, flags, rqtp, \ + rmtp) \ + __sanitizer_syscall_pre_impl_clock_nanosleep( \ (long)(which_clock), (long)(flags), (long)(rqtp), (long)(rmtp)) -#define __sanitizer_syscall_post_clock_nanosleep(res, which_clock, flags, \ - rqtp, rmtp) \ - __sanitizer_syscall_post_impl_clock_nanosleep( \ +#define __sanitizer_syscall_post_clock_nanosleep(res, which_clock, flags, \ + rqtp, rmtp) \ + __sanitizer_syscall_post_impl_clock_nanosleep( \ res, (long)(which_clock), (long)(flags), (long)(rqtp), (long)(rmtp)) -#define __sanitizer_syscall_pre_nice(increment) \ +#define __sanitizer_syscall_pre_nice(increment) \ __sanitizer_syscall_pre_impl_nice((long)(increment)) -#define __sanitizer_syscall_post_nice(res, increment) \ +#define __sanitizer_syscall_post_nice(res, increment) \ __sanitizer_syscall_post_impl_nice(res, (long)(increment)) #define __sanitizer_syscall_pre_sched_setscheduler(pid, policy, param) \ __sanitizer_syscall_pre_impl_sched_setscheduler((long)(pid), (long)(policy), \ (long)(param)) -#define __sanitizer_syscall_post_sched_setscheduler(res, pid, policy, param) \ - __sanitizer_syscall_post_impl_sched_setscheduler( \ +#define __sanitizer_syscall_post_sched_setscheduler(res, pid, policy, param) \ + __sanitizer_syscall_post_impl_sched_setscheduler( \ res, (long)(pid), (long)(policy), (long)(param)) -#define __sanitizer_syscall_pre_sched_setparam(pid, param) \ +#define __sanitizer_syscall_pre_sched_setparam(pid, param) \ __sanitizer_syscall_pre_impl_sched_setparam((long)(pid), (long)(param)) -#define __sanitizer_syscall_post_sched_setparam(res, pid, param) \ +#define __sanitizer_syscall_post_sched_setparam(res, pid, param) \ __sanitizer_syscall_post_impl_sched_setparam(res, (long)(pid), (long)(param)) -#define __sanitizer_syscall_pre_sched_getscheduler(pid) \ +#define __sanitizer_syscall_pre_sched_getscheduler(pid) \ __sanitizer_syscall_pre_impl_sched_getscheduler((long)(pid)) -#define __sanitizer_syscall_post_sched_getscheduler(res, pid) \ +#define __sanitizer_syscall_post_sched_getscheduler(res, pid) \ __sanitizer_syscall_post_impl_sched_getscheduler(res, (long)(pid)) -#define __sanitizer_syscall_pre_sched_getparam(pid, param) \ +#define __sanitizer_syscall_pre_sched_getparam(pid, param) \ __sanitizer_syscall_pre_impl_sched_getparam((long)(pid), (long)(param)) -#define __sanitizer_syscall_post_sched_getparam(res, pid, param) \ +#define __sanitizer_syscall_post_sched_getparam(res, pid, param) \ __sanitizer_syscall_post_impl_sched_getparam(res, (long)(pid), (long)(param)) -#define __sanitizer_syscall_pre_sched_setaffinity(pid, len, user_mask_ptr) \ - __sanitizer_syscall_pre_impl_sched_setaffinity((long)(pid), (long)(len), \ +#define __sanitizer_syscall_pre_sched_setaffinity(pid, len, user_mask_ptr) \ + __sanitizer_syscall_pre_impl_sched_setaffinity((long)(pid), (long)(len), \ (long)(user_mask_ptr)) -#define __sanitizer_syscall_post_sched_setaffinity(res, pid, len, \ - user_mask_ptr) \ - __sanitizer_syscall_post_impl_sched_setaffinity( \ +#define __sanitizer_syscall_post_sched_setaffinity(res, pid, len, \ + user_mask_ptr) \ + __sanitizer_syscall_post_impl_sched_setaffinity( \ res, (long)(pid), (long)(len), (long)(user_mask_ptr)) -#define __sanitizer_syscall_pre_sched_getaffinity(pid, len, user_mask_ptr) \ - __sanitizer_syscall_pre_impl_sched_getaffinity((long)(pid), (long)(len), \ +#define __sanitizer_syscall_pre_sched_getaffinity(pid, len, user_mask_ptr) \ + __sanitizer_syscall_pre_impl_sched_getaffinity((long)(pid), (long)(len), \ (long)(user_mask_ptr)) -#define __sanitizer_syscall_post_sched_getaffinity(res, pid, len, \ - user_mask_ptr) \ - __sanitizer_syscall_post_impl_sched_getaffinity( \ +#define __sanitizer_syscall_post_sched_getaffinity(res, pid, len, \ + user_mask_ptr) \ + __sanitizer_syscall_post_impl_sched_getaffinity( \ res, (long)(pid), (long)(len), (long)(user_mask_ptr)) -#define __sanitizer_syscall_pre_sched_yield() \ +#define __sanitizer_syscall_pre_sched_yield() \ __sanitizer_syscall_pre_impl_sched_yield() -#define __sanitizer_syscall_post_sched_yield(res) \ +#define __sanitizer_syscall_post_sched_yield(res) \ __sanitizer_syscall_post_impl_sched_yield(res) -#define __sanitizer_syscall_pre_sched_get_priority_max(policy) \ +#define __sanitizer_syscall_pre_sched_get_priority_max(policy) \ __sanitizer_syscall_pre_impl_sched_get_priority_max((long)(policy)) -#define __sanitizer_syscall_post_sched_get_priority_max(res, policy) \ +#define __sanitizer_syscall_post_sched_get_priority_max(res, policy) \ __sanitizer_syscall_post_impl_sched_get_priority_max(res, (long)(policy)) -#define __sanitizer_syscall_pre_sched_get_priority_min(policy) \ +#define __sanitizer_syscall_pre_sched_get_priority_min(policy) \ __sanitizer_syscall_pre_impl_sched_get_priority_min((long)(policy)) -#define __sanitizer_syscall_post_sched_get_priority_min(res, policy) \ +#define __sanitizer_syscall_post_sched_get_priority_min(res, policy) \ __sanitizer_syscall_post_impl_sched_get_priority_min(res, (long)(policy)) -#define __sanitizer_syscall_pre_sched_rr_get_interval(pid, interval) \ - __sanitizer_syscall_pre_impl_sched_rr_get_interval((long)(pid), \ +#define __sanitizer_syscall_pre_sched_rr_get_interval(pid, interval) \ + __sanitizer_syscall_pre_impl_sched_rr_get_interval((long)(pid), \ (long)(interval)) -#define __sanitizer_syscall_post_sched_rr_get_interval(res, pid, interval) \ - __sanitizer_syscall_post_impl_sched_rr_get_interval(res, (long)(pid), \ +#define __sanitizer_syscall_post_sched_rr_get_interval(res, pid, interval) \ + __sanitizer_syscall_post_impl_sched_rr_get_interval(res, (long)(pid), \ (long)(interval)) -#define __sanitizer_syscall_pre_setpriority(which, who, niceval) \ - __sanitizer_syscall_pre_impl_setpriority((long)(which), (long)(who), \ +#define __sanitizer_syscall_pre_setpriority(which, who, niceval) \ + __sanitizer_syscall_pre_impl_setpriority((long)(which), (long)(who), \ (long)(niceval)) -#define __sanitizer_syscall_post_setpriority(res, which, who, niceval) \ - __sanitizer_syscall_post_impl_setpriority(res, (long)(which), (long)(who), \ +#define __sanitizer_syscall_post_setpriority(res, which, who, niceval) \ + __sanitizer_syscall_post_impl_setpriority(res, (long)(which), (long)(who), \ (long)(niceval)) -#define __sanitizer_syscall_pre_getpriority(which, who) \ +#define __sanitizer_syscall_pre_getpriority(which, who) \ __sanitizer_syscall_pre_impl_getpriority((long)(which), (long)(who)) -#define __sanitizer_syscall_post_getpriority(res, which, who) \ +#define __sanitizer_syscall_post_getpriority(res, which, who) \ __sanitizer_syscall_post_impl_getpriority(res, (long)(which), (long)(who)) -#define __sanitizer_syscall_pre_shutdown(arg0, arg1) \ +#define __sanitizer_syscall_pre_shutdown(arg0, arg1) \ __sanitizer_syscall_pre_impl_shutdown((long)(arg0), (long)(arg1)) -#define __sanitizer_syscall_post_shutdown(res, arg0, arg1) \ +#define __sanitizer_syscall_post_shutdown(res, arg0, arg1) \ __sanitizer_syscall_post_impl_shutdown(res, (long)(arg0), (long)(arg1)) -#define __sanitizer_syscall_pre_reboot(magic1, magic2, cmd, arg) \ - __sanitizer_syscall_pre_impl_reboot((long)(magic1), (long)(magic2), \ +#define __sanitizer_syscall_pre_reboot(magic1, magic2, cmd, arg) \ + __sanitizer_syscall_pre_impl_reboot((long)(magic1), (long)(magic2), \ (long)(cmd), (long)(arg)) -#define __sanitizer_syscall_post_reboot(res, magic1, magic2, cmd, arg) \ - __sanitizer_syscall_post_impl_reboot(res, (long)(magic1), (long)(magic2), \ +#define __sanitizer_syscall_post_reboot(res, magic1, magic2, cmd, arg) \ + __sanitizer_syscall_post_impl_reboot(res, (long)(magic1), (long)(magic2), \ (long)(cmd), (long)(arg)) -#define __sanitizer_syscall_pre_restart_syscall() \ +#define __sanitizer_syscall_pre_restart_syscall() \ __sanitizer_syscall_pre_impl_restart_syscall() -#define __sanitizer_syscall_post_restart_syscall(res) \ +#define __sanitizer_syscall_post_restart_syscall(res) \ __sanitizer_syscall_post_impl_restart_syscall(res) -#define __sanitizer_syscall_pre_kexec_load(entry, nr_segments, segments, \ - flags) \ - __sanitizer_syscall_pre_impl_kexec_load((long)(entry), (long)(nr_segments), \ +#define __sanitizer_syscall_pre_kexec_load(entry, nr_segments, segments, \ + flags) \ + __sanitizer_syscall_pre_impl_kexec_load((long)(entry), (long)(nr_segments), \ (long)(segments), (long)(flags)) #define __sanitizer_syscall_post_kexec_load(res, entry, nr_segments, segments, \ flags) \ __sanitizer_syscall_post_impl_kexec_load(res, (long)(entry), \ (long)(nr_segments), \ (long)(segments), (long)(flags)) -#define __sanitizer_syscall_pre_exit(error_code) \ +#define __sanitizer_syscall_pre_exit(error_code) \ __sanitizer_syscall_pre_impl_exit((long)(error_code)) -#define __sanitizer_syscall_post_exit(res, error_code) \ +#define __sanitizer_syscall_post_exit(res, error_code) \ __sanitizer_syscall_post_impl_exit(res, (long)(error_code)) -#define __sanitizer_syscall_pre_exit_group(error_code) \ +#define __sanitizer_syscall_pre_exit_group(error_code) \ __sanitizer_syscall_pre_impl_exit_group((long)(error_code)) -#define __sanitizer_syscall_post_exit_group(res, error_code) \ +#define __sanitizer_syscall_post_exit_group(res, error_code) \ __sanitizer_syscall_post_impl_exit_group(res, (long)(error_code)) -#define __sanitizer_syscall_pre_wait4(pid, stat_addr, options, ru) \ - __sanitizer_syscall_pre_impl_wait4((long)(pid), (long)(stat_addr), \ +#define __sanitizer_syscall_pre_wait4(pid, stat_addr, options, ru) \ + __sanitizer_syscall_pre_impl_wait4((long)(pid), (long)(stat_addr), \ (long)(options), (long)(ru)) -#define __sanitizer_syscall_post_wait4(res, pid, stat_addr, options, ru) \ - __sanitizer_syscall_post_impl_wait4(res, (long)(pid), (long)(stat_addr), \ +#define __sanitizer_syscall_post_wait4(res, pid, stat_addr, options, ru) \ + __sanitizer_syscall_post_impl_wait4(res, (long)(pid), (long)(stat_addr), \ (long)(options), (long)(ru)) -#define __sanitizer_syscall_pre_waitid(which, pid, infop, options, ru) \ - __sanitizer_syscall_pre_impl_waitid( \ +#define __sanitizer_syscall_pre_waitid(which, pid, infop, options, ru) \ + __sanitizer_syscall_pre_impl_waitid( \ (long)(which), (long)(pid), (long)(infop), (long)(options), (long)(ru)) -#define __sanitizer_syscall_post_waitid(res, which, pid, infop, options, ru) \ - __sanitizer_syscall_post_impl_waitid(res, (long)(which), (long)(pid), \ - (long)(infop), (long)(options), \ +#define __sanitizer_syscall_post_waitid(res, which, pid, infop, options, ru) \ + __sanitizer_syscall_post_impl_waitid(res, (long)(which), (long)(pid), \ + (long)(infop), (long)(options), \ (long)(ru)) -#define __sanitizer_syscall_pre_waitpid(pid, stat_addr, options) \ - __sanitizer_syscall_pre_impl_waitpid((long)(pid), (long)(stat_addr), \ +#define __sanitizer_syscall_pre_waitpid(pid, stat_addr, options) \ + __sanitizer_syscall_pre_impl_waitpid((long)(pid), (long)(stat_addr), \ (long)(options)) -#define __sanitizer_syscall_post_waitpid(res, pid, stat_addr, options) \ - __sanitizer_syscall_post_impl_waitpid(res, (long)(pid), (long)(stat_addr), \ +#define __sanitizer_syscall_post_waitpid(res, pid, stat_addr, options) \ + __sanitizer_syscall_post_impl_waitpid(res, (long)(pid), (long)(stat_addr), \ (long)(options)) -#define __sanitizer_syscall_pre_set_tid_address(tidptr) \ +#define __sanitizer_syscall_pre_set_tid_address(tidptr) \ __sanitizer_syscall_pre_impl_set_tid_address((long)(tidptr)) -#define __sanitizer_syscall_post_set_tid_address(res, tidptr) \ +#define __sanitizer_syscall_post_set_tid_address(res, tidptr) \ __sanitizer_syscall_post_impl_set_tid_address(res, (long)(tidptr)) -#define __sanitizer_syscall_pre_init_module(umod, len, uargs) \ - __sanitizer_syscall_pre_impl_init_module((long)(umod), (long)(len), \ +#define __sanitizer_syscall_pre_init_module(umod, len, uargs) \ + __sanitizer_syscall_pre_impl_init_module((long)(umod), (long)(len), \ (long)(uargs)) -#define __sanitizer_syscall_post_init_module(res, umod, len, uargs) \ - __sanitizer_syscall_post_impl_init_module(res, (long)(umod), (long)(len), \ +#define __sanitizer_syscall_post_init_module(res, umod, len, uargs) \ + __sanitizer_syscall_post_impl_init_module(res, (long)(umod), (long)(len), \ (long)(uargs)) -#define __sanitizer_syscall_pre_delete_module(name_user, flags) \ +#define __sanitizer_syscall_pre_delete_module(name_user, flags) \ __sanitizer_syscall_pre_impl_delete_module((long)(name_user), (long)(flags)) -#define __sanitizer_syscall_post_delete_module(res, name_user, flags) \ - __sanitizer_syscall_post_impl_delete_module(res, (long)(name_user), \ +#define __sanitizer_syscall_post_delete_module(res, name_user, flags) \ + __sanitizer_syscall_post_impl_delete_module(res, (long)(name_user), \ (long)(flags)) -#define __sanitizer_syscall_pre_rt_sigprocmask(how, set, oset, sigsetsize) \ - __sanitizer_syscall_pre_impl_rt_sigprocmask( \ +#define __sanitizer_syscall_pre_rt_sigprocmask(how, set, oset, sigsetsize) \ + __sanitizer_syscall_pre_impl_rt_sigprocmask( \ (long)(how), (long)(set), (long)(oset), (long)(sigsetsize)) -#define __sanitizer_syscall_post_rt_sigprocmask(res, how, set, oset, \ - sigsetsize) \ - __sanitizer_syscall_post_impl_rt_sigprocmask( \ +#define __sanitizer_syscall_post_rt_sigprocmask(res, how, set, oset, \ + sigsetsize) \ + __sanitizer_syscall_post_impl_rt_sigprocmask( \ res, (long)(how), (long)(set), (long)(oset), (long)(sigsetsize)) -#define __sanitizer_syscall_pre_rt_sigpending(set, sigsetsize) \ +#define __sanitizer_syscall_pre_rt_sigpending(set, sigsetsize) \ __sanitizer_syscall_pre_impl_rt_sigpending((long)(set), (long)(sigsetsize)) -#define __sanitizer_syscall_post_rt_sigpending(res, set, sigsetsize) \ - __sanitizer_syscall_post_impl_rt_sigpending(res, (long)(set), \ +#define __sanitizer_syscall_post_rt_sigpending(res, set, sigsetsize) \ + __sanitizer_syscall_post_impl_rt_sigpending(res, (long)(set), \ (long)(sigsetsize)) -#define __sanitizer_syscall_pre_rt_sigtimedwait(uthese, uinfo, uts, \ - sigsetsize) \ - __sanitizer_syscall_pre_impl_rt_sigtimedwait( \ +#define __sanitizer_syscall_pre_rt_sigtimedwait(uthese, uinfo, uts, \ + sigsetsize) \ + __sanitizer_syscall_pre_impl_rt_sigtimedwait( \ (long)(uthese), (long)(uinfo), (long)(uts), (long)(sigsetsize)) -#define __sanitizer_syscall_post_rt_sigtimedwait(res, uthese, uinfo, uts, \ - sigsetsize) \ - __sanitizer_syscall_post_impl_rt_sigtimedwait( \ +#define __sanitizer_syscall_post_rt_sigtimedwait(res, uthese, uinfo, uts, \ + sigsetsize) \ + __sanitizer_syscall_post_impl_rt_sigtimedwait( \ res, (long)(uthese), (long)(uinfo), (long)(uts), (long)(sigsetsize)) -#define __sanitizer_syscall_pre_rt_tgsigqueueinfo(tgid, pid, sig, uinfo) \ - __sanitizer_syscall_pre_impl_rt_tgsigqueueinfo((long)(tgid), (long)(pid), \ +#define __sanitizer_syscall_pre_rt_tgsigqueueinfo(tgid, pid, sig, uinfo) \ + __sanitizer_syscall_pre_impl_rt_tgsigqueueinfo((long)(tgid), (long)(pid), \ (long)(sig), (long)(uinfo)) #define __sanitizer_syscall_post_rt_tgsigqueueinfo(res, tgid, pid, sig, uinfo) \ __sanitizer_syscall_post_impl_rt_tgsigqueueinfo( \ res, (long)(tgid), (long)(pid), (long)(sig), (long)(uinfo)) -#define __sanitizer_syscall_pre_kill(pid, sig) \ +#define __sanitizer_syscall_pre_kill(pid, sig) \ __sanitizer_syscall_pre_impl_kill((long)(pid), (long)(sig)) -#define __sanitizer_syscall_post_kill(res, pid, sig) \ +#define __sanitizer_syscall_post_kill(res, pid, sig) \ __sanitizer_syscall_post_impl_kill(res, (long)(pid), (long)(sig)) -#define __sanitizer_syscall_pre_tgkill(tgid, pid, sig) \ +#define __sanitizer_syscall_pre_tgkill(tgid, pid, sig) \ __sanitizer_syscall_pre_impl_tgkill((long)(tgid), (long)(pid), (long)(sig)) -#define __sanitizer_syscall_post_tgkill(res, tgid, pid, sig) \ - __sanitizer_syscall_post_impl_tgkill(res, (long)(tgid), (long)(pid), \ +#define __sanitizer_syscall_post_tgkill(res, tgid, pid, sig) \ + __sanitizer_syscall_post_impl_tgkill(res, (long)(tgid), (long)(pid), \ (long)(sig)) -#define __sanitizer_syscall_pre_tkill(pid, sig) \ +#define __sanitizer_syscall_pre_tkill(pid, sig) \ __sanitizer_syscall_pre_impl_tkill((long)(pid), (long)(sig)) -#define __sanitizer_syscall_post_tkill(res, pid, sig) \ +#define __sanitizer_syscall_post_tkill(res, pid, sig) \ __sanitizer_syscall_post_impl_tkill(res, (long)(pid), (long)(sig)) -#define __sanitizer_syscall_pre_rt_sigqueueinfo(pid, sig, uinfo) \ - __sanitizer_syscall_pre_impl_rt_sigqueueinfo((long)(pid), (long)(sig), \ +#define __sanitizer_syscall_pre_rt_sigqueueinfo(pid, sig, uinfo) \ + __sanitizer_syscall_pre_impl_rt_sigqueueinfo((long)(pid), (long)(sig), \ (long)(uinfo)) #define __sanitizer_syscall_post_rt_sigqueueinfo(res, pid, sig, uinfo) \ __sanitizer_syscall_post_impl_rt_sigqueueinfo(res, (long)(pid), (long)(sig), \ (long)(uinfo)) -#define __sanitizer_syscall_pre_sgetmask() \ +#define __sanitizer_syscall_pre_sgetmask() \ __sanitizer_syscall_pre_impl_sgetmask() -#define __sanitizer_syscall_post_sgetmask(res) \ +#define __sanitizer_syscall_post_sgetmask(res) \ __sanitizer_syscall_post_impl_sgetmask(res) -#define __sanitizer_syscall_pre_ssetmask(newmask) \ +#define __sanitizer_syscall_pre_ssetmask(newmask) \ __sanitizer_syscall_pre_impl_ssetmask((long)(newmask)) -#define __sanitizer_syscall_post_ssetmask(res, newmask) \ +#define __sanitizer_syscall_post_ssetmask(res, newmask) \ __sanitizer_syscall_post_impl_ssetmask(res, (long)(newmask)) -#define __sanitizer_syscall_pre_signal(sig, handler) \ +#define __sanitizer_syscall_pre_signal(sig, handler) \ __sanitizer_syscall_pre_impl_signal((long)(sig), (long)(handler)) -#define __sanitizer_syscall_post_signal(res, sig, handler) \ +#define __sanitizer_syscall_post_signal(res, sig, handler) \ __sanitizer_syscall_post_impl_signal(res, (long)(sig), (long)(handler)) #define __sanitizer_syscall_pre_pause() __sanitizer_syscall_pre_impl_pause() -#define __sanitizer_syscall_post_pause(res) \ +#define __sanitizer_syscall_post_pause(res) \ __sanitizer_syscall_post_impl_pause(res) #define __sanitizer_syscall_pre_sync() __sanitizer_syscall_pre_impl_sync() -#define __sanitizer_syscall_post_sync(res) \ +#define __sanitizer_syscall_post_sync(res) \ __sanitizer_syscall_post_impl_sync(res) -#define __sanitizer_syscall_pre_fsync(fd) \ +#define __sanitizer_syscall_pre_fsync(fd) \ __sanitizer_syscall_pre_impl_fsync((long)(fd)) -#define __sanitizer_syscall_post_fsync(res, fd) \ +#define __sanitizer_syscall_post_fsync(res, fd) \ __sanitizer_syscall_post_impl_fsync(res, (long)(fd)) -#define __sanitizer_syscall_pre_fdatasync(fd) \ +#define __sanitizer_syscall_pre_fdatasync(fd) \ __sanitizer_syscall_pre_impl_fdatasync((long)(fd)) -#define __sanitizer_syscall_post_fdatasync(res, fd) \ +#define __sanitizer_syscall_post_fdatasync(res, fd) \ __sanitizer_syscall_post_impl_fdatasync(res, (long)(fd)) -#define __sanitizer_syscall_pre_bdflush(func, data) \ +#define __sanitizer_syscall_pre_bdflush(func, data) \ __sanitizer_syscall_pre_impl_bdflush((long)(func), (long)(data)) -#define __sanitizer_syscall_post_bdflush(res, func, data) \ +#define __sanitizer_syscall_post_bdflush(res, func, data) \ __sanitizer_syscall_post_impl_bdflush(res, (long)(func), (long)(data)) -#define __sanitizer_syscall_pre_mount(dev_name, dir_name, type, flags, data) \ - __sanitizer_syscall_pre_impl_mount((long)(dev_name), (long)(dir_name), \ - (long)(type), (long)(flags), \ +#define __sanitizer_syscall_pre_mount(dev_name, dir_name, type, flags, data) \ + __sanitizer_syscall_pre_impl_mount((long)(dev_name), (long)(dir_name), \ + (long)(type), (long)(flags), \ (long)(data)) #define __sanitizer_syscall_post_mount(res, dev_name, dir_name, type, flags, \ data) \ __sanitizer_syscall_post_impl_mount(res, (long)(dev_name), (long)(dir_name), \ (long)(type), (long)(flags), \ (long)(data)) -#define __sanitizer_syscall_pre_umount(name, flags) \ +#define __sanitizer_syscall_pre_umount(name, flags) \ __sanitizer_syscall_pre_impl_umount((long)(name), (long)(flags)) -#define __sanitizer_syscall_post_umount(res, name, flags) \ +#define __sanitizer_syscall_post_umount(res, name, flags) \ __sanitizer_syscall_post_impl_umount(res, (long)(name), (long)(flags)) -#define __sanitizer_syscall_pre_oldumount(name) \ +#define __sanitizer_syscall_pre_oldumount(name) \ __sanitizer_syscall_pre_impl_oldumount((long)(name)) -#define __sanitizer_syscall_post_oldumount(res, name) \ +#define __sanitizer_syscall_post_oldumount(res, name) \ __sanitizer_syscall_post_impl_oldumount(res, (long)(name)) -#define __sanitizer_syscall_pre_truncate(path, length) \ +#define __sanitizer_syscall_pre_truncate(path, length) \ __sanitizer_syscall_pre_impl_truncate((long)(path), (long)(length)) -#define __sanitizer_syscall_post_truncate(res, path, length) \ +#define __sanitizer_syscall_post_truncate(res, path, length) \ __sanitizer_syscall_post_impl_truncate(res, (long)(path), (long)(length)) -#define __sanitizer_syscall_pre_ftruncate(fd, length) \ +#define __sanitizer_syscall_pre_ftruncate(fd, length) \ __sanitizer_syscall_pre_impl_ftruncate((long)(fd), (long)(length)) -#define __sanitizer_syscall_post_ftruncate(res, fd, length) \ +#define __sanitizer_syscall_post_ftruncate(res, fd, length) \ __sanitizer_syscall_post_impl_ftruncate(res, (long)(fd), (long)(length)) -#define __sanitizer_syscall_pre_stat(filename, statbuf) \ +#define __sanitizer_syscall_pre_stat(filename, statbuf) \ __sanitizer_syscall_pre_impl_stat((long)(filename), (long)(statbuf)) -#define __sanitizer_syscall_post_stat(res, filename, statbuf) \ +#define __sanitizer_syscall_post_stat(res, filename, statbuf) \ __sanitizer_syscall_post_impl_stat(res, (long)(filename), (long)(statbuf)) -#define __sanitizer_syscall_pre_statfs(path, buf) \ +#define __sanitizer_syscall_pre_statfs(path, buf) \ __sanitizer_syscall_pre_impl_statfs((long)(path), (long)(buf)) -#define __sanitizer_syscall_post_statfs(res, path, buf) \ +#define __sanitizer_syscall_post_statfs(res, path, buf) \ __sanitizer_syscall_post_impl_statfs(res, (long)(path), (long)(buf)) -#define __sanitizer_syscall_pre_statfs64(path, sz, buf) \ +#define __sanitizer_syscall_pre_statfs64(path, sz, buf) \ __sanitizer_syscall_pre_impl_statfs64((long)(path), (long)(sz), (long)(buf)) -#define __sanitizer_syscall_post_statfs64(res, path, sz, buf) \ - __sanitizer_syscall_post_impl_statfs64(res, (long)(path), (long)(sz), \ +#define __sanitizer_syscall_post_statfs64(res, path, sz, buf) \ + __sanitizer_syscall_post_impl_statfs64(res, (long)(path), (long)(sz), \ (long)(buf)) -#define __sanitizer_syscall_pre_fstatfs(fd, buf) \ +#define __sanitizer_syscall_pre_fstatfs(fd, buf) \ __sanitizer_syscall_pre_impl_fstatfs((long)(fd), (long)(buf)) -#define __sanitizer_syscall_post_fstatfs(res, fd, buf) \ +#define __sanitizer_syscall_post_fstatfs(res, fd, buf) \ __sanitizer_syscall_post_impl_fstatfs(res, (long)(fd), (long)(buf)) -#define __sanitizer_syscall_pre_fstatfs64(fd, sz, buf) \ +#define __sanitizer_syscall_pre_fstatfs64(fd, sz, buf) \ __sanitizer_syscall_pre_impl_fstatfs64((long)(fd), (long)(sz), (long)(buf)) -#define __sanitizer_syscall_post_fstatfs64(res, fd, sz, buf) \ - __sanitizer_syscall_post_impl_fstatfs64(res, (long)(fd), (long)(sz), \ +#define __sanitizer_syscall_post_fstatfs64(res, fd, sz, buf) \ + __sanitizer_syscall_post_impl_fstatfs64(res, (long)(fd), (long)(sz), \ (long)(buf)) -#define __sanitizer_syscall_pre_lstat(filename, statbuf) \ +#define __sanitizer_syscall_pre_lstat(filename, statbuf) \ __sanitizer_syscall_pre_impl_lstat((long)(filename), (long)(statbuf)) -#define __sanitizer_syscall_post_lstat(res, filename, statbuf) \ +#define __sanitizer_syscall_post_lstat(res, filename, statbuf) \ __sanitizer_syscall_post_impl_lstat(res, (long)(filename), (long)(statbuf)) -#define __sanitizer_syscall_pre_fstat(fd, statbuf) \ +#define __sanitizer_syscall_pre_fstat(fd, statbuf) \ __sanitizer_syscall_pre_impl_fstat((long)(fd), (long)(statbuf)) -#define __sanitizer_syscall_post_fstat(res, fd, statbuf) \ +#define __sanitizer_syscall_post_fstat(res, fd, statbuf) \ __sanitizer_syscall_post_impl_fstat(res, (long)(fd), (long)(statbuf)) -#define __sanitizer_syscall_pre_newstat(filename, statbuf) \ +#define __sanitizer_syscall_pre_newstat(filename, statbuf) \ __sanitizer_syscall_pre_impl_newstat((long)(filename), (long)(statbuf)) -#define __sanitizer_syscall_post_newstat(res, filename, statbuf) \ +#define __sanitizer_syscall_post_newstat(res, filename, statbuf) \ __sanitizer_syscall_post_impl_newstat(res, (long)(filename), (long)(statbuf)) -#define __sanitizer_syscall_pre_newlstat(filename, statbuf) \ +#define __sanitizer_syscall_pre_newlstat(filename, statbuf) \ __sanitizer_syscall_pre_impl_newlstat((long)(filename), (long)(statbuf)) -#define __sanitizer_syscall_post_newlstat(res, filename, statbuf) \ +#define __sanitizer_syscall_post_newlstat(res, filename, statbuf) \ __sanitizer_syscall_post_impl_newlstat(res, (long)(filename), (long)(statbuf)) -#define __sanitizer_syscall_pre_newfstat(fd, statbuf) \ +#define __sanitizer_syscall_pre_newfstat(fd, statbuf) \ __sanitizer_syscall_pre_impl_newfstat((long)(fd), (long)(statbuf)) -#define __sanitizer_syscall_post_newfstat(res, fd, statbuf) \ +#define __sanitizer_syscall_post_newfstat(res, fd, statbuf) \ __sanitizer_syscall_post_impl_newfstat(res, (long)(fd), (long)(statbuf)) -#define __sanitizer_syscall_pre_ustat(dev, ubuf) \ +#define __sanitizer_syscall_pre_ustat(dev, ubuf) \ __sanitizer_syscall_pre_impl_ustat((long)(dev), (long)(ubuf)) -#define __sanitizer_syscall_post_ustat(res, dev, ubuf) \ +#define __sanitizer_syscall_post_ustat(res, dev, ubuf) \ __sanitizer_syscall_post_impl_ustat(res, (long)(dev), (long)(ubuf)) -#define __sanitizer_syscall_pre_stat64(filename, statbuf) \ +#define __sanitizer_syscall_pre_stat64(filename, statbuf) \ __sanitizer_syscall_pre_impl_stat64((long)(filename), (long)(statbuf)) -#define __sanitizer_syscall_post_stat64(res, filename, statbuf) \ +#define __sanitizer_syscall_post_stat64(res, filename, statbuf) \ __sanitizer_syscall_post_impl_stat64(res, (long)(filename), (long)(statbuf)) -#define __sanitizer_syscall_pre_fstat64(fd, statbuf) \ +#define __sanitizer_syscall_pre_fstat64(fd, statbuf) \ __sanitizer_syscall_pre_impl_fstat64((long)(fd), (long)(statbuf)) -#define __sanitizer_syscall_post_fstat64(res, fd, statbuf) \ +#define __sanitizer_syscall_post_fstat64(res, fd, statbuf) \ __sanitizer_syscall_post_impl_fstat64(res, (long)(fd), (long)(statbuf)) -#define __sanitizer_syscall_pre_lstat64(filename, statbuf) \ +#define __sanitizer_syscall_pre_lstat64(filename, statbuf) \ __sanitizer_syscall_pre_impl_lstat64((long)(filename), (long)(statbuf)) -#define __sanitizer_syscall_post_lstat64(res, filename, statbuf) \ +#define __sanitizer_syscall_post_lstat64(res, filename, statbuf) \ __sanitizer_syscall_post_impl_lstat64(res, (long)(filename), (long)(statbuf)) -#define __sanitizer_syscall_pre_setxattr(path, name, value, size, flags) \ - __sanitizer_syscall_pre_impl_setxattr( \ +#define __sanitizer_syscall_pre_setxattr(path, name, value, size, flags) \ + __sanitizer_syscall_pre_impl_setxattr( \ (long)(path), (long)(name), (long)(value), (long)(size), (long)(flags)) #define __sanitizer_syscall_post_setxattr(res, path, name, value, size, flags) \ __sanitizer_syscall_post_impl_setxattr(res, (long)(path), (long)(name), \ (long)(value), (long)(size), \ (long)(flags)) -#define __sanitizer_syscall_pre_lsetxattr(path, name, value, size, flags) \ - __sanitizer_syscall_pre_impl_lsetxattr( \ +#define __sanitizer_syscall_pre_lsetxattr(path, name, value, size, flags) \ + __sanitizer_syscall_pre_impl_lsetxattr( \ (long)(path), (long)(name), (long)(value), (long)(size), (long)(flags)) -#define __sanitizer_syscall_post_lsetxattr(res, path, name, value, size, \ - flags) \ - __sanitizer_syscall_post_impl_lsetxattr(res, (long)(path), (long)(name), \ - (long)(value), (long)(size), \ +#define __sanitizer_syscall_post_lsetxattr(res, path, name, value, size, \ + flags) \ + __sanitizer_syscall_post_impl_lsetxattr(res, (long)(path), (long)(name), \ + (long)(value), (long)(size), \ (long)(flags)) -#define __sanitizer_syscall_pre_fsetxattr(fd, name, value, size, flags) \ - __sanitizer_syscall_pre_impl_fsetxattr( \ +#define __sanitizer_syscall_pre_fsetxattr(fd, name, value, size, flags) \ + __sanitizer_syscall_pre_impl_fsetxattr( \ (long)(fd), (long)(name), (long)(value), (long)(size), (long)(flags)) -#define __sanitizer_syscall_post_fsetxattr(res, fd, name, value, size, flags) \ - __sanitizer_syscall_post_impl_fsetxattr(res, (long)(fd), (long)(name), \ - (long)(value), (long)(size), \ +#define __sanitizer_syscall_post_fsetxattr(res, fd, name, value, size, flags) \ + __sanitizer_syscall_post_impl_fsetxattr(res, (long)(fd), (long)(name), \ + (long)(value), (long)(size), \ (long)(flags)) -#define __sanitizer_syscall_pre_getxattr(path, name, value, size) \ - __sanitizer_syscall_pre_impl_getxattr((long)(path), (long)(name), \ +#define __sanitizer_syscall_pre_getxattr(path, name, value, size) \ + __sanitizer_syscall_pre_impl_getxattr((long)(path), (long)(name), \ (long)(value), (long)(size)) -#define __sanitizer_syscall_post_getxattr(res, path, name, value, size) \ - __sanitizer_syscall_post_impl_getxattr(res, (long)(path), (long)(name), \ +#define __sanitizer_syscall_post_getxattr(res, path, name, value, size) \ + __sanitizer_syscall_post_impl_getxattr(res, (long)(path), (long)(name), \ (long)(value), (long)(size)) -#define __sanitizer_syscall_pre_lgetxattr(path, name, value, size) \ - __sanitizer_syscall_pre_impl_lgetxattr((long)(path), (long)(name), \ +#define __sanitizer_syscall_pre_lgetxattr(path, name, value, size) \ + __sanitizer_syscall_pre_impl_lgetxattr((long)(path), (long)(name), \ (long)(value), (long)(size)) -#define __sanitizer_syscall_post_lgetxattr(res, path, name, value, size) \ - __sanitizer_syscall_post_impl_lgetxattr(res, (long)(path), (long)(name), \ +#define __sanitizer_syscall_post_lgetxattr(res, path, name, value, size) \ + __sanitizer_syscall_post_impl_lgetxattr(res, (long)(path), (long)(name), \ (long)(value), (long)(size)) -#define __sanitizer_syscall_pre_fgetxattr(fd, name, value, size) \ - __sanitizer_syscall_pre_impl_fgetxattr((long)(fd), (long)(name), \ +#define __sanitizer_syscall_pre_fgetxattr(fd, name, value, size) \ + __sanitizer_syscall_pre_impl_fgetxattr((long)(fd), (long)(name), \ (long)(value), (long)(size)) -#define __sanitizer_syscall_post_fgetxattr(res, fd, name, value, size) \ - __sanitizer_syscall_post_impl_fgetxattr(res, (long)(fd), (long)(name), \ +#define __sanitizer_syscall_post_fgetxattr(res, fd, name, value, size) \ + __sanitizer_syscall_post_impl_fgetxattr(res, (long)(fd), (long)(name), \ (long)(value), (long)(size)) -#define __sanitizer_syscall_pre_listxattr(path, list, size) \ - __sanitizer_syscall_pre_impl_listxattr((long)(path), (long)(list), \ +#define __sanitizer_syscall_pre_listxattr(path, list, size) \ + __sanitizer_syscall_pre_impl_listxattr((long)(path), (long)(list), \ (long)(size)) -#define __sanitizer_syscall_post_listxattr(res, path, list, size) \ - __sanitizer_syscall_post_impl_listxattr(res, (long)(path), (long)(list), \ +#define __sanitizer_syscall_post_listxattr(res, path, list, size) \ + __sanitizer_syscall_post_impl_listxattr(res, (long)(path), (long)(list), \ (long)(size)) -#define __sanitizer_syscall_pre_llistxattr(path, list, size) \ - __sanitizer_syscall_pre_impl_llistxattr((long)(path), (long)(list), \ +#define __sanitizer_syscall_pre_llistxattr(path, list, size) \ + __sanitizer_syscall_pre_impl_llistxattr((long)(path), (long)(list), \ (long)(size)) -#define __sanitizer_syscall_post_llistxattr(res, path, list, size) \ - __sanitizer_syscall_post_impl_llistxattr(res, (long)(path), (long)(list), \ +#define __sanitizer_syscall_post_llistxattr(res, path, list, size) \ + __sanitizer_syscall_post_impl_llistxattr(res, (long)(path), (long)(list), \ (long)(size)) -#define __sanitizer_syscall_pre_flistxattr(fd, list, size) \ - __sanitizer_syscall_pre_impl_flistxattr((long)(fd), (long)(list), \ +#define __sanitizer_syscall_pre_flistxattr(fd, list, size) \ + __sanitizer_syscall_pre_impl_flistxattr((long)(fd), (long)(list), \ (long)(size)) -#define __sanitizer_syscall_post_flistxattr(res, fd, list, size) \ - __sanitizer_syscall_post_impl_flistxattr(res, (long)(fd), (long)(list), \ +#define __sanitizer_syscall_post_flistxattr(res, fd, list, size) \ + __sanitizer_syscall_post_impl_flistxattr(res, (long)(fd), (long)(list), \ (long)(size)) -#define __sanitizer_syscall_pre_removexattr(path, name) \ +#define __sanitizer_syscall_pre_removexattr(path, name) \ __sanitizer_syscall_pre_impl_removexattr((long)(path), (long)(name)) -#define __sanitizer_syscall_post_removexattr(res, path, name) \ +#define __sanitizer_syscall_post_removexattr(res, path, name) \ __sanitizer_syscall_post_impl_removexattr(res, (long)(path), (long)(name)) -#define __sanitizer_syscall_pre_lremovexattr(path, name) \ +#define __sanitizer_syscall_pre_lremovexattr(path, name) \ __sanitizer_syscall_pre_impl_lremovexattr((long)(path), (long)(name)) -#define __sanitizer_syscall_post_lremovexattr(res, path, name) \ +#define __sanitizer_syscall_post_lremovexattr(res, path, name) \ __sanitizer_syscall_post_impl_lremovexattr(res, (long)(path), (long)(name)) -#define __sanitizer_syscall_pre_fremovexattr(fd, name) \ +#define __sanitizer_syscall_pre_fremovexattr(fd, name) \ __sanitizer_syscall_pre_impl_fremovexattr((long)(fd), (long)(name)) -#define __sanitizer_syscall_post_fremovexattr(res, fd, name) \ +#define __sanitizer_syscall_post_fremovexattr(res, fd, name) \ __sanitizer_syscall_post_impl_fremovexattr(res, (long)(fd), (long)(name)) -#define __sanitizer_syscall_pre_brk(brk) \ +#define __sanitizer_syscall_pre_brk(brk) \ __sanitizer_syscall_pre_impl_brk((long)(brk)) -#define __sanitizer_syscall_post_brk(res, brk) \ +#define __sanitizer_syscall_post_brk(res, brk) \ __sanitizer_syscall_post_impl_brk(res, (long)(brk)) -#define __sanitizer_syscall_pre_mprotect(start, len, prot) \ - __sanitizer_syscall_pre_impl_mprotect((long)(start), (long)(len), \ +#define __sanitizer_syscall_pre_mprotect(start, len, prot) \ + __sanitizer_syscall_pre_impl_mprotect((long)(start), (long)(len), \ (long)(prot)) -#define __sanitizer_syscall_post_mprotect(res, start, len, prot) \ - __sanitizer_syscall_post_impl_mprotect(res, (long)(start), (long)(len), \ +#define __sanitizer_syscall_post_mprotect(res, start, len, prot) \ + __sanitizer_syscall_post_impl_mprotect(res, (long)(start), (long)(len), \ (long)(prot)) -#define __sanitizer_syscall_pre_mremap(addr, old_len, new_len, flags, \ - new_addr) \ - __sanitizer_syscall_pre_impl_mremap((long)(addr), (long)(old_len), \ - (long)(new_len), (long)(flags), \ +#define __sanitizer_syscall_pre_mremap(addr, old_len, new_len, flags, \ + new_addr) \ + __sanitizer_syscall_pre_impl_mremap((long)(addr), (long)(old_len), \ + (long)(new_len), (long)(flags), \ (long)(new_addr)) -#define __sanitizer_syscall_post_mremap(res, addr, old_len, new_len, flags, \ - new_addr) \ - __sanitizer_syscall_post_impl_mremap(res, (long)(addr), (long)(old_len), \ - (long)(new_len), (long)(flags), \ +#define __sanitizer_syscall_post_mremap(res, addr, old_len, new_len, flags, \ + new_addr) \ + __sanitizer_syscall_post_impl_mremap(res, (long)(addr), (long)(old_len), \ + (long)(new_len), (long)(flags), \ (long)(new_addr)) -#define __sanitizer_syscall_pre_remap_file_pages(start, size, prot, pgoff, \ - flags) \ - __sanitizer_syscall_pre_impl_remap_file_pages( \ +#define __sanitizer_syscall_pre_remap_file_pages(start, size, prot, pgoff, \ + flags) \ + __sanitizer_syscall_pre_impl_remap_file_pages( \ (long)(start), (long)(size), (long)(prot), (long)(pgoff), (long)(flags)) -#define __sanitizer_syscall_post_remap_file_pages(res, start, size, prot, \ - pgoff, flags) \ - __sanitizer_syscall_post_impl_remap_file_pages(res, (long)(start), \ - (long)(size), (long)(prot), \ +#define __sanitizer_syscall_post_remap_file_pages(res, start, size, prot, \ + pgoff, flags) \ + __sanitizer_syscall_post_impl_remap_file_pages(res, (long)(start), \ + (long)(size), (long)(prot), \ (long)(pgoff), (long)(flags)) -#define __sanitizer_syscall_pre_msync(start, len, flags) \ +#define __sanitizer_syscall_pre_msync(start, len, flags) \ __sanitizer_syscall_pre_impl_msync((long)(start), (long)(len), (long)(flags)) -#define __sanitizer_syscall_post_msync(res, start, len, flags) \ - __sanitizer_syscall_post_impl_msync(res, (long)(start), (long)(len), \ +#define __sanitizer_syscall_post_msync(res, start, len, flags) \ + __sanitizer_syscall_post_impl_msync(res, (long)(start), (long)(len), \ (long)(flags)) -#define __sanitizer_syscall_pre_munmap(addr, len) \ +#define __sanitizer_syscall_pre_munmap(addr, len) \ __sanitizer_syscall_pre_impl_munmap((long)(addr), (long)(len)) -#define __sanitizer_syscall_post_munmap(res, addr, len) \ +#define __sanitizer_syscall_post_munmap(res, addr, len) \ __sanitizer_syscall_post_impl_munmap(res, (long)(addr), (long)(len)) -#define __sanitizer_syscall_pre_mlock(start, len) \ +#define __sanitizer_syscall_pre_mlock(start, len) \ __sanitizer_syscall_pre_impl_mlock((long)(start), (long)(len)) -#define __sanitizer_syscall_post_mlock(res, start, len) \ +#define __sanitizer_syscall_post_mlock(res, start, len) \ __sanitizer_syscall_post_impl_mlock(res, (long)(start), (long)(len)) -#define __sanitizer_syscall_pre_munlock(start, len) \ +#define __sanitizer_syscall_pre_munlock(start, len) \ __sanitizer_syscall_pre_impl_munlock((long)(start), (long)(len)) -#define __sanitizer_syscall_post_munlock(res, start, len) \ +#define __sanitizer_syscall_post_munlock(res, start, len) \ __sanitizer_syscall_post_impl_munlock(res, (long)(start), (long)(len)) -#define __sanitizer_syscall_pre_mlockall(flags) \ +#define __sanitizer_syscall_pre_mlockall(flags) \ __sanitizer_syscall_pre_impl_mlockall((long)(flags)) -#define __sanitizer_syscall_post_mlockall(res, flags) \ +#define __sanitizer_syscall_post_mlockall(res, flags) \ __sanitizer_syscall_post_impl_mlockall(res, (long)(flags)) -#define __sanitizer_syscall_pre_munlockall() \ +#define __sanitizer_syscall_pre_munlockall() \ __sanitizer_syscall_pre_impl_munlockall() -#define __sanitizer_syscall_post_munlockall(res) \ +#define __sanitizer_syscall_post_munlockall(res) \ __sanitizer_syscall_post_impl_munlockall(res) -#define __sanitizer_syscall_pre_madvise(start, len, behavior) \ - __sanitizer_syscall_pre_impl_madvise((long)(start), (long)(len), \ +#define __sanitizer_syscall_pre_madvise(start, len, behavior) \ + __sanitizer_syscall_pre_impl_madvise((long)(start), (long)(len), \ (long)(behavior)) -#define __sanitizer_syscall_post_madvise(res, start, len, behavior) \ - __sanitizer_syscall_post_impl_madvise(res, (long)(start), (long)(len), \ +#define __sanitizer_syscall_post_madvise(res, start, len, behavior) \ + __sanitizer_syscall_post_impl_madvise(res, (long)(start), (long)(len), \ (long)(behavior)) -#define __sanitizer_syscall_pre_mincore(start, len, vec) \ +#define __sanitizer_syscall_pre_mincore(start, len, vec) \ __sanitizer_syscall_pre_impl_mincore((long)(start), (long)(len), (long)(vec)) -#define __sanitizer_syscall_post_mincore(res, start, len, vec) \ - __sanitizer_syscall_post_impl_mincore(res, (long)(start), (long)(len), \ +#define __sanitizer_syscall_post_mincore(res, start, len, vec) \ + __sanitizer_syscall_post_impl_mincore(res, (long)(start), (long)(len), \ (long)(vec)) -#define __sanitizer_syscall_pre_pivot_root(new_root, put_old) \ +#define __sanitizer_syscall_pre_pivot_root(new_root, put_old) \ __sanitizer_syscall_pre_impl_pivot_root((long)(new_root), (long)(put_old)) -#define __sanitizer_syscall_post_pivot_root(res, new_root, put_old) \ - __sanitizer_syscall_post_impl_pivot_root(res, (long)(new_root), \ +#define __sanitizer_syscall_post_pivot_root(res, new_root, put_old) \ + __sanitizer_syscall_post_impl_pivot_root(res, (long)(new_root), \ (long)(put_old)) -#define __sanitizer_syscall_pre_chroot(filename) \ +#define __sanitizer_syscall_pre_chroot(filename) \ __sanitizer_syscall_pre_impl_chroot((long)(filename)) -#define __sanitizer_syscall_post_chroot(res, filename) \ +#define __sanitizer_syscall_post_chroot(res, filename) \ __sanitizer_syscall_post_impl_chroot(res, (long)(filename)) -#define __sanitizer_syscall_pre_mknod(filename, mode, dev) \ - __sanitizer_syscall_pre_impl_mknod((long)(filename), (long)(mode), \ +#define __sanitizer_syscall_pre_mknod(filename, mode, dev) \ + __sanitizer_syscall_pre_impl_mknod((long)(filename), (long)(mode), \ (long)(dev)) -#define __sanitizer_syscall_post_mknod(res, filename, mode, dev) \ - __sanitizer_syscall_post_impl_mknod(res, (long)(filename), (long)(mode), \ +#define __sanitizer_syscall_post_mknod(res, filename, mode, dev) \ + __sanitizer_syscall_post_impl_mknod(res, (long)(filename), (long)(mode), \ (long)(dev)) -#define __sanitizer_syscall_pre_link(oldname, newname) \ +#define __sanitizer_syscall_pre_link(oldname, newname) \ __sanitizer_syscall_pre_impl_link((long)(oldname), (long)(newname)) -#define __sanitizer_syscall_post_link(res, oldname, newname) \ +#define __sanitizer_syscall_post_link(res, oldname, newname) \ __sanitizer_syscall_post_impl_link(res, (long)(oldname), (long)(newname)) -#define __sanitizer_syscall_pre_symlink(old, new_) \ +#define __sanitizer_syscall_pre_symlink(old, new_) \ __sanitizer_syscall_pre_impl_symlink((long)(old), (long)(new_)) -#define __sanitizer_syscall_post_symlink(res, old, new_) \ +#define __sanitizer_syscall_post_symlink(res, old, new_) \ __sanitizer_syscall_post_impl_symlink(res, (long)(old), (long)(new_)) -#define __sanitizer_syscall_pre_unlink(pathname) \ +#define __sanitizer_syscall_pre_unlink(pathname) \ __sanitizer_syscall_pre_impl_unlink((long)(pathname)) -#define __sanitizer_syscall_post_unlink(res, pathname) \ +#define __sanitizer_syscall_post_unlink(res, pathname) \ __sanitizer_syscall_post_impl_unlink(res, (long)(pathname)) -#define __sanitizer_syscall_pre_rename(oldname, newname) \ +#define __sanitizer_syscall_pre_rename(oldname, newname) \ __sanitizer_syscall_pre_impl_rename((long)(oldname), (long)(newname)) -#define __sanitizer_syscall_post_rename(res, oldname, newname) \ +#define __sanitizer_syscall_post_rename(res, oldname, newname) \ __sanitizer_syscall_post_impl_rename(res, (long)(oldname), (long)(newname)) -#define __sanitizer_syscall_pre_chmod(filename, mode) \ +#define __sanitizer_syscall_pre_chmod(filename, mode) \ __sanitizer_syscall_pre_impl_chmod((long)(filename), (long)(mode)) -#define __sanitizer_syscall_post_chmod(res, filename, mode) \ +#define __sanitizer_syscall_post_chmod(res, filename, mode) \ __sanitizer_syscall_post_impl_chmod(res, (long)(filename), (long)(mode)) -#define __sanitizer_syscall_pre_fchmod(fd, mode) \ +#define __sanitizer_syscall_pre_fchmod(fd, mode) \ __sanitizer_syscall_pre_impl_fchmod((long)(fd), (long)(mode)) -#define __sanitizer_syscall_post_fchmod(res, fd, mode) \ +#define __sanitizer_syscall_post_fchmod(res, fd, mode) \ __sanitizer_syscall_post_impl_fchmod(res, (long)(fd), (long)(mode)) -#define __sanitizer_syscall_pre_fcntl(fd, cmd, arg) \ +#define __sanitizer_syscall_pre_fcntl(fd, cmd, arg) \ __sanitizer_syscall_pre_impl_fcntl((long)(fd), (long)(cmd), (long)(arg)) -#define __sanitizer_syscall_post_fcntl(res, fd, cmd, arg) \ +#define __sanitizer_syscall_post_fcntl(res, fd, cmd, arg) \ __sanitizer_syscall_post_impl_fcntl(res, (long)(fd), (long)(cmd), (long)(arg)) -#define __sanitizer_syscall_pre_fcntl64(fd, cmd, arg) \ +#define __sanitizer_syscall_pre_fcntl64(fd, cmd, arg) \ __sanitizer_syscall_pre_impl_fcntl64((long)(fd), (long)(cmd), (long)(arg)) -#define __sanitizer_syscall_post_fcntl64(res, fd, cmd, arg) \ - __sanitizer_syscall_post_impl_fcntl64(res, (long)(fd), (long)(cmd), \ +#define __sanitizer_syscall_post_fcntl64(res, fd, cmd, arg) \ + __sanitizer_syscall_post_impl_fcntl64(res, (long)(fd), (long)(cmd), \ (long)(arg)) -#define __sanitizer_syscall_pre_pipe(fildes) \ +#define __sanitizer_syscall_pre_pipe(fildes) \ __sanitizer_syscall_pre_impl_pipe((long)(fildes)) -#define __sanitizer_syscall_post_pipe(res, fildes) \ +#define __sanitizer_syscall_post_pipe(res, fildes) \ __sanitizer_syscall_post_impl_pipe(res, (long)(fildes)) -#define __sanitizer_syscall_pre_pipe2(fildes, flags) \ +#define __sanitizer_syscall_pre_pipe2(fildes, flags) \ __sanitizer_syscall_pre_impl_pipe2((long)(fildes), (long)(flags)) -#define __sanitizer_syscall_post_pipe2(res, fildes, flags) \ +#define __sanitizer_syscall_post_pipe2(res, fildes, flags) \ __sanitizer_syscall_post_impl_pipe2(res, (long)(fildes), (long)(flags)) -#define __sanitizer_syscall_pre_dup(fildes) \ +#define __sanitizer_syscall_pre_dup(fildes) \ __sanitizer_syscall_pre_impl_dup((long)(fildes)) -#define __sanitizer_syscall_post_dup(res, fildes) \ +#define __sanitizer_syscall_post_dup(res, fildes) \ __sanitizer_syscall_post_impl_dup(res, (long)(fildes)) -#define __sanitizer_syscall_pre_dup2(oldfd, newfd) \ +#define __sanitizer_syscall_pre_dup2(oldfd, newfd) \ __sanitizer_syscall_pre_impl_dup2((long)(oldfd), (long)(newfd)) -#define __sanitizer_syscall_post_dup2(res, oldfd, newfd) \ +#define __sanitizer_syscall_post_dup2(res, oldfd, newfd) \ __sanitizer_syscall_post_impl_dup2(res, (long)(oldfd), (long)(newfd)) -#define __sanitizer_syscall_pre_dup3(oldfd, newfd, flags) \ +#define __sanitizer_syscall_pre_dup3(oldfd, newfd, flags) \ __sanitizer_syscall_pre_impl_dup3((long)(oldfd), (long)(newfd), (long)(flags)) -#define __sanitizer_syscall_post_dup3(res, oldfd, newfd, flags) \ - __sanitizer_syscall_post_impl_dup3(res, (long)(oldfd), (long)(newfd), \ +#define __sanitizer_syscall_post_dup3(res, oldfd, newfd, flags) \ + __sanitizer_syscall_post_impl_dup3(res, (long)(oldfd), (long)(newfd), \ (long)(flags)) -#define __sanitizer_syscall_pre_ioperm(from, num, on) \ +#define __sanitizer_syscall_pre_ioperm(from, num, on) \ __sanitizer_syscall_pre_impl_ioperm((long)(from), (long)(num), (long)(on)) -#define __sanitizer_syscall_post_ioperm(res, from, num, on) \ - __sanitizer_syscall_post_impl_ioperm(res, (long)(from), (long)(num), \ +#define __sanitizer_syscall_post_ioperm(res, from, num, on) \ + __sanitizer_syscall_post_impl_ioperm(res, (long)(from), (long)(num), \ (long)(on)) -#define __sanitizer_syscall_pre_ioctl(fd, cmd, arg) \ +#define __sanitizer_syscall_pre_ioctl(fd, cmd, arg) \ __sanitizer_syscall_pre_impl_ioctl((long)(fd), (long)(cmd), (long)(arg)) -#define __sanitizer_syscall_post_ioctl(res, fd, cmd, arg) \ +#define __sanitizer_syscall_post_ioctl(res, fd, cmd, arg) \ __sanitizer_syscall_post_impl_ioctl(res, (long)(fd), (long)(cmd), (long)(arg)) -#define __sanitizer_syscall_pre_flock(fd, cmd) \ +#define __sanitizer_syscall_pre_flock(fd, cmd) \ __sanitizer_syscall_pre_impl_flock((long)(fd), (long)(cmd)) -#define __sanitizer_syscall_post_flock(res, fd, cmd) \ +#define __sanitizer_syscall_post_flock(res, fd, cmd) \ __sanitizer_syscall_post_impl_flock(res, (long)(fd), (long)(cmd)) -#define __sanitizer_syscall_pre_io_setup(nr_reqs, ctx) \ +#define __sanitizer_syscall_pre_io_setup(nr_reqs, ctx) \ __sanitizer_syscall_pre_impl_io_setup((long)(nr_reqs), (long)(ctx)) -#define __sanitizer_syscall_post_io_setup(res, nr_reqs, ctx) \ +#define __sanitizer_syscall_post_io_setup(res, nr_reqs, ctx) \ __sanitizer_syscall_post_impl_io_setup(res, (long)(nr_reqs), (long)(ctx)) -#define __sanitizer_syscall_pre_io_destroy(ctx) \ +#define __sanitizer_syscall_pre_io_destroy(ctx) \ __sanitizer_syscall_pre_impl_io_destroy((long)(ctx)) -#define __sanitizer_syscall_post_io_destroy(res, ctx) \ +#define __sanitizer_syscall_post_io_destroy(res, ctx) \ __sanitizer_syscall_post_impl_io_destroy(res, (long)(ctx)) -#define __sanitizer_syscall_pre_io_getevents(ctx_id, min_nr, nr, events, \ - timeout) \ - __sanitizer_syscall_pre_impl_io_getevents((long)(ctx_id), (long)(min_nr), \ - (long)(nr), (long)(events), \ +#define __sanitizer_syscall_pre_io_getevents(ctx_id, min_nr, nr, events, \ + timeout) \ + __sanitizer_syscall_pre_impl_io_getevents((long)(ctx_id), (long)(min_nr), \ + (long)(nr), (long)(events), \ (long)(timeout)) #define __sanitizer_syscall_post_io_getevents(res, ctx_id, min_nr, nr, events, \ timeout) \ __sanitizer_syscall_post_impl_io_getevents(res, (long)(ctx_id), \ (long)(min_nr), (long)(nr), \ (long)(events), (long)(timeout)) -#define __sanitizer_syscall_pre_io_submit(ctx_id, arg1, arg2) \ - __sanitizer_syscall_pre_impl_io_submit((long)(ctx_id), (long)(arg1), \ +#define __sanitizer_syscall_pre_io_submit(ctx_id, arg1, arg2) \ + __sanitizer_syscall_pre_impl_io_submit((long)(ctx_id), (long)(arg1), \ (long)(arg2)) -#define __sanitizer_syscall_post_io_submit(res, ctx_id, arg1, arg2) \ - __sanitizer_syscall_post_impl_io_submit(res, (long)(ctx_id), (long)(arg1), \ +#define __sanitizer_syscall_post_io_submit(res, ctx_id, arg1, arg2) \ + __sanitizer_syscall_post_impl_io_submit(res, (long)(ctx_id), (long)(arg1), \ (long)(arg2)) -#define __sanitizer_syscall_pre_io_cancel(ctx_id, iocb, result) \ - __sanitizer_syscall_pre_impl_io_cancel((long)(ctx_id), (long)(iocb), \ +#define __sanitizer_syscall_pre_io_cancel(ctx_id, iocb, result) \ + __sanitizer_syscall_pre_impl_io_cancel((long)(ctx_id), (long)(iocb), \ (long)(result)) -#define __sanitizer_syscall_post_io_cancel(res, ctx_id, iocb, result) \ - __sanitizer_syscall_post_impl_io_cancel(res, (long)(ctx_id), (long)(iocb), \ +#define __sanitizer_syscall_post_io_cancel(res, ctx_id, iocb, result) \ + __sanitizer_syscall_post_impl_io_cancel(res, (long)(ctx_id), (long)(iocb), \ (long)(result)) -#define __sanitizer_syscall_pre_sendfile(out_fd, in_fd, offset, count) \ - __sanitizer_syscall_pre_impl_sendfile((long)(out_fd), (long)(in_fd), \ +#define __sanitizer_syscall_pre_sendfile(out_fd, in_fd, offset, count) \ + __sanitizer_syscall_pre_impl_sendfile((long)(out_fd), (long)(in_fd), \ (long)(offset), (long)(count)) -#define __sanitizer_syscall_post_sendfile(res, out_fd, in_fd, offset, count) \ - __sanitizer_syscall_post_impl_sendfile(res, (long)(out_fd), (long)(in_fd), \ +#define __sanitizer_syscall_post_sendfile(res, out_fd, in_fd, offset, count) \ + __sanitizer_syscall_post_impl_sendfile(res, (long)(out_fd), (long)(in_fd), \ (long)(offset), (long)(count)) -#define __sanitizer_syscall_pre_sendfile64(out_fd, in_fd, offset, count) \ - __sanitizer_syscall_pre_impl_sendfile64((long)(out_fd), (long)(in_fd), \ +#define __sanitizer_syscall_pre_sendfile64(out_fd, in_fd, offset, count) \ + __sanitizer_syscall_pre_impl_sendfile64((long)(out_fd), (long)(in_fd), \ (long)(offset), (long)(count)) #define __sanitizer_syscall_post_sendfile64(res, out_fd, in_fd, offset, count) \ __sanitizer_syscall_post_impl_sendfile64(res, (long)(out_fd), (long)(in_fd), \ (long)(offset), (long)(count)) -#define __sanitizer_syscall_pre_readlink(path, buf, bufsiz) \ - __sanitizer_syscall_pre_impl_readlink((long)(path), (long)(buf), \ +#define __sanitizer_syscall_pre_readlink(path, buf, bufsiz) \ + __sanitizer_syscall_pre_impl_readlink((long)(path), (long)(buf), \ (long)(bufsiz)) -#define __sanitizer_syscall_post_readlink(res, path, buf, bufsiz) \ - __sanitizer_syscall_post_impl_readlink(res, (long)(path), (long)(buf), \ +#define __sanitizer_syscall_post_readlink(res, path, buf, bufsiz) \ + __sanitizer_syscall_post_impl_readlink(res, (long)(path), (long)(buf), \ (long)(bufsiz)) -#define __sanitizer_syscall_pre_creat(pathname, mode) \ +#define __sanitizer_syscall_pre_creat(pathname, mode) \ __sanitizer_syscall_pre_impl_creat((long)(pathname), (long)(mode)) -#define __sanitizer_syscall_post_creat(res, pathname, mode) \ +#define __sanitizer_syscall_post_creat(res, pathname, mode) \ __sanitizer_syscall_post_impl_creat(res, (long)(pathname), (long)(mode)) -#define __sanitizer_syscall_pre_open(filename, flags, mode) \ - __sanitizer_syscall_pre_impl_open((long)(filename), (long)(flags), \ +#define __sanitizer_syscall_pre_open(filename, flags, mode) \ + __sanitizer_syscall_pre_impl_open((long)(filename), (long)(flags), \ (long)(mode)) -#define __sanitizer_syscall_post_open(res, filename, flags, mode) \ - __sanitizer_syscall_post_impl_open(res, (long)(filename), (long)(flags), \ +#define __sanitizer_syscall_post_open(res, filename, flags, mode) \ + __sanitizer_syscall_post_impl_open(res, (long)(filename), (long)(flags), \ (long)(mode)) -#define __sanitizer_syscall_pre_close(fd) \ +#define __sanitizer_syscall_pre_close(fd) \ __sanitizer_syscall_pre_impl_close((long)(fd)) -#define __sanitizer_syscall_post_close(res, fd) \ +#define __sanitizer_syscall_post_close(res, fd) \ __sanitizer_syscall_post_impl_close(res, (long)(fd)) -#define __sanitizer_syscall_pre_access(filename, mode) \ +#define __sanitizer_syscall_pre_access(filename, mode) \ __sanitizer_syscall_pre_impl_access((long)(filename), (long)(mode)) -#define __sanitizer_syscall_post_access(res, filename, mode) \ +#define __sanitizer_syscall_post_access(res, filename, mode) \ __sanitizer_syscall_post_impl_access(res, (long)(filename), (long)(mode)) #define __sanitizer_syscall_pre_vhangup() __sanitizer_syscall_pre_impl_vhangup() -#define __sanitizer_syscall_post_vhangup(res) \ +#define __sanitizer_syscall_post_vhangup(res) \ __sanitizer_syscall_post_impl_vhangup(res) -#define __sanitizer_syscall_pre_chown(filename, user, group) \ - __sanitizer_syscall_pre_impl_chown((long)(filename), (long)(user), \ +#define __sanitizer_syscall_pre_chown(filename, user, group) \ + __sanitizer_syscall_pre_impl_chown((long)(filename), (long)(user), \ (long)(group)) -#define __sanitizer_syscall_post_chown(res, filename, user, group) \ - __sanitizer_syscall_post_impl_chown(res, (long)(filename), (long)(user), \ +#define __sanitizer_syscall_post_chown(res, filename, user, group) \ + __sanitizer_syscall_post_impl_chown(res, (long)(filename), (long)(user), \ (long)(group)) -#define __sanitizer_syscall_pre_lchown(filename, user, group) \ - __sanitizer_syscall_pre_impl_lchown((long)(filename), (long)(user), \ +#define __sanitizer_syscall_pre_lchown(filename, user, group) \ + __sanitizer_syscall_pre_impl_lchown((long)(filename), (long)(user), \ (long)(group)) -#define __sanitizer_syscall_post_lchown(res, filename, user, group) \ - __sanitizer_syscall_post_impl_lchown(res, (long)(filename), (long)(user), \ +#define __sanitizer_syscall_post_lchown(res, filename, user, group) \ + __sanitizer_syscall_post_impl_lchown(res, (long)(filename), (long)(user), \ (long)(group)) -#define __sanitizer_syscall_pre_fchown(fd, user, group) \ +#define __sanitizer_syscall_pre_fchown(fd, user, group) \ __sanitizer_syscall_pre_impl_fchown((long)(fd), (long)(user), (long)(group)) -#define __sanitizer_syscall_post_fchown(res, fd, user, group) \ - __sanitizer_syscall_post_impl_fchown(res, (long)(fd), (long)(user), \ +#define __sanitizer_syscall_post_fchown(res, fd, user, group) \ + __sanitizer_syscall_post_impl_fchown(res, (long)(fd), (long)(user), \ (long)(group)) -#define __sanitizer_syscall_pre_chown16(filename, user, group) \ - __sanitizer_syscall_pre_impl_chown16((long)(filename), (long)user, \ +#define __sanitizer_syscall_pre_chown16(filename, user, group) \ + __sanitizer_syscall_pre_impl_chown16((long)(filename), (long)user, \ (long)group) -#define __sanitizer_syscall_post_chown16(res, filename, user, group) \ - __sanitizer_syscall_post_impl_chown16(res, (long)(filename), (long)user, \ +#define __sanitizer_syscall_post_chown16(res, filename, user, group) \ + __sanitizer_syscall_post_impl_chown16(res, (long)(filename), (long)user, \ (long)group) -#define __sanitizer_syscall_pre_lchown16(filename, user, group) \ - __sanitizer_syscall_pre_impl_lchown16((long)(filename), (long)user, \ +#define __sanitizer_syscall_pre_lchown16(filename, user, group) \ + __sanitizer_syscall_pre_impl_lchown16((long)(filename), (long)user, \ (long)group) -#define __sanitizer_syscall_post_lchown16(res, filename, user, group) \ - __sanitizer_syscall_post_impl_lchown16(res, (long)(filename), (long)user, \ +#define __sanitizer_syscall_post_lchown16(res, filename, user, group) \ + __sanitizer_syscall_post_impl_lchown16(res, (long)(filename), (long)user, \ (long)group) -#define __sanitizer_syscall_pre_fchown16(fd, user, group) \ +#define __sanitizer_syscall_pre_fchown16(fd, user, group) \ __sanitizer_syscall_pre_impl_fchown16((long)(fd), (long)user, (long)group) -#define __sanitizer_syscall_post_fchown16(res, fd, user, group) \ - __sanitizer_syscall_post_impl_fchown16(res, (long)(fd), (long)user, \ +#define __sanitizer_syscall_post_fchown16(res, fd, user, group) \ + __sanitizer_syscall_post_impl_fchown16(res, (long)(fd), (long)user, \ (long)group) -#define __sanitizer_syscall_pre_setregid16(rgid, egid) \ +#define __sanitizer_syscall_pre_setregid16(rgid, egid) \ __sanitizer_syscall_pre_impl_setregid16((long)rgid, (long)egid) -#define __sanitizer_syscall_post_setregid16(res, rgid, egid) \ +#define __sanitizer_syscall_post_setregid16(res, rgid, egid) \ __sanitizer_syscall_post_impl_setregid16(res, (long)rgid, (long)egid) -#define __sanitizer_syscall_pre_setgid16(gid) \ +#define __sanitizer_syscall_pre_setgid16(gid) \ __sanitizer_syscall_pre_impl_setgid16((long)gid) -#define __sanitizer_syscall_post_setgid16(res, gid) \ +#define __sanitizer_syscall_post_setgid16(res, gid) \ __sanitizer_syscall_post_impl_setgid16(res, (long)gid) -#define __sanitizer_syscall_pre_setreuid16(ruid, euid) \ +#define __sanitizer_syscall_pre_setreuid16(ruid, euid) \ __sanitizer_syscall_pre_impl_setreuid16((long)ruid, (long)euid) -#define __sanitizer_syscall_post_setreuid16(res, ruid, euid) \ +#define __sanitizer_syscall_post_setreuid16(res, ruid, euid) \ __sanitizer_syscall_post_impl_setreuid16(res, (long)ruid, (long)euid) -#define __sanitizer_syscall_pre_setuid16(uid) \ +#define __sanitizer_syscall_pre_setuid16(uid) \ __sanitizer_syscall_pre_impl_setuid16((long)uid) -#define __sanitizer_syscall_post_setuid16(res, uid) \ +#define __sanitizer_syscall_post_setuid16(res, uid) \ __sanitizer_syscall_post_impl_setuid16(res, (long)uid) -#define __sanitizer_syscall_pre_setresuid16(ruid, euid, suid) \ +#define __sanitizer_syscall_pre_setresuid16(ruid, euid, suid) \ __sanitizer_syscall_pre_impl_setresuid16((long)ruid, (long)euid, (long)suid) -#define __sanitizer_syscall_post_setresuid16(res, ruid, euid, suid) \ - __sanitizer_syscall_post_impl_setresuid16(res, (long)ruid, (long)euid, \ +#define __sanitizer_syscall_post_setresuid16(res, ruid, euid, suid) \ + __sanitizer_syscall_post_impl_setresuid16(res, (long)ruid, (long)euid, \ (long)suid) -#define __sanitizer_syscall_pre_getresuid16(ruid, euid, suid) \ - __sanitizer_syscall_pre_impl_getresuid16((long)(ruid), (long)(euid), \ +#define __sanitizer_syscall_pre_getresuid16(ruid, euid, suid) \ + __sanitizer_syscall_pre_impl_getresuid16((long)(ruid), (long)(euid), \ (long)(suid)) -#define __sanitizer_syscall_post_getresuid16(res, ruid, euid, suid) \ - __sanitizer_syscall_post_impl_getresuid16(res, (long)(ruid), (long)(euid), \ +#define __sanitizer_syscall_post_getresuid16(res, ruid, euid, suid) \ + __sanitizer_syscall_post_impl_getresuid16(res, (long)(ruid), (long)(euid), \ (long)(suid)) -#define __sanitizer_syscall_pre_setresgid16(rgid, egid, sgid) \ +#define __sanitizer_syscall_pre_setresgid16(rgid, egid, sgid) \ __sanitizer_syscall_pre_impl_setresgid16((long)rgid, (long)egid, (long)sgid) -#define __sanitizer_syscall_post_setresgid16(res, rgid, egid, sgid) \ - __sanitizer_syscall_post_impl_setresgid16(res, (long)rgid, (long)egid, \ +#define __sanitizer_syscall_post_setresgid16(res, rgid, egid, sgid) \ + __sanitizer_syscall_post_impl_setresgid16(res, (long)rgid, (long)egid, \ (long)sgid) -#define __sanitizer_syscall_pre_getresgid16(rgid, egid, sgid) \ - __sanitizer_syscall_pre_impl_getresgid16((long)(rgid), (long)(egid), \ +#define __sanitizer_syscall_pre_getresgid16(rgid, egid, sgid) \ + __sanitizer_syscall_pre_impl_getresgid16((long)(rgid), (long)(egid), \ (long)(sgid)) -#define __sanitizer_syscall_post_getresgid16(res, rgid, egid, sgid) \ - __sanitizer_syscall_post_impl_getresgid16(res, (long)(rgid), (long)(egid), \ +#define __sanitizer_syscall_post_getresgid16(res, rgid, egid, sgid) \ + __sanitizer_syscall_post_impl_getresgid16(res, (long)(rgid), (long)(egid), \ (long)(sgid)) -#define __sanitizer_syscall_pre_setfsuid16(uid) \ +#define __sanitizer_syscall_pre_setfsuid16(uid) \ __sanitizer_syscall_pre_impl_setfsuid16((long)uid) -#define __sanitizer_syscall_post_setfsuid16(res, uid) \ +#define __sanitizer_syscall_post_setfsuid16(res, uid) \ __sanitizer_syscall_post_impl_setfsuid16(res, (long)uid) -#define __sanitizer_syscall_pre_setfsgid16(gid) \ +#define __sanitizer_syscall_pre_setfsgid16(gid) \ __sanitizer_syscall_pre_impl_setfsgid16((long)gid) -#define __sanitizer_syscall_post_setfsgid16(res, gid) \ +#define __sanitizer_syscall_post_setfsgid16(res, gid) \ __sanitizer_syscall_post_impl_setfsgid16(res, (long)gid) -#define __sanitizer_syscall_pre_getgroups16(gidsetsize, grouplist) \ - __sanitizer_syscall_pre_impl_getgroups16((long)(gidsetsize), \ +#define __sanitizer_syscall_pre_getgroups16(gidsetsize, grouplist) \ + __sanitizer_syscall_pre_impl_getgroups16((long)(gidsetsize), \ (long)(grouplist)) -#define __sanitizer_syscall_post_getgroups16(res, gidsetsize, grouplist) \ - __sanitizer_syscall_post_impl_getgroups16(res, (long)(gidsetsize), \ +#define __sanitizer_syscall_post_getgroups16(res, gidsetsize, grouplist) \ + __sanitizer_syscall_post_impl_getgroups16(res, (long)(gidsetsize), \ (long)(grouplist)) -#define __sanitizer_syscall_pre_setgroups16(gidsetsize, grouplist) \ - __sanitizer_syscall_pre_impl_setgroups16((long)(gidsetsize), \ +#define __sanitizer_syscall_pre_setgroups16(gidsetsize, grouplist) \ + __sanitizer_syscall_pre_impl_setgroups16((long)(gidsetsize), \ (long)(grouplist)) -#define __sanitizer_syscall_post_setgroups16(res, gidsetsize, grouplist) \ - __sanitizer_syscall_post_impl_setgroups16(res, (long)(gidsetsize), \ +#define __sanitizer_syscall_post_setgroups16(res, gidsetsize, grouplist) \ + __sanitizer_syscall_post_impl_setgroups16(res, (long)(gidsetsize), \ (long)(grouplist)) -#define __sanitizer_syscall_pre_getuid16() \ +#define __sanitizer_syscall_pre_getuid16() \ __sanitizer_syscall_pre_impl_getuid16() -#define __sanitizer_syscall_post_getuid16(res) \ +#define __sanitizer_syscall_post_getuid16(res) \ __sanitizer_syscall_post_impl_getuid16(res) -#define __sanitizer_syscall_pre_geteuid16() \ +#define __sanitizer_syscall_pre_geteuid16() \ __sanitizer_syscall_pre_impl_geteuid16() -#define __sanitizer_syscall_post_geteuid16(res) \ +#define __sanitizer_syscall_post_geteuid16(res) \ __sanitizer_syscall_post_impl_geteuid16(res) -#define __sanitizer_syscall_pre_getgid16() \ +#define __sanitizer_syscall_pre_getgid16() \ __sanitizer_syscall_pre_impl_getgid16() -#define __sanitizer_syscall_post_getgid16(res) \ +#define __sanitizer_syscall_post_getgid16(res) \ __sanitizer_syscall_post_impl_getgid16(res) -#define __sanitizer_syscall_pre_getegid16() \ +#define __sanitizer_syscall_pre_getegid16() \ __sanitizer_syscall_pre_impl_getegid16() -#define __sanitizer_syscall_post_getegid16(res) \ +#define __sanitizer_syscall_post_getegid16(res) \ __sanitizer_syscall_post_impl_getegid16(res) -#define __sanitizer_syscall_pre_utime(filename, times) \ +#define __sanitizer_syscall_pre_utime(filename, times) \ __sanitizer_syscall_pre_impl_utime((long)(filename), (long)(times)) -#define __sanitizer_syscall_post_utime(res, filename, times) \ +#define __sanitizer_syscall_post_utime(res, filename, times) \ __sanitizer_syscall_post_impl_utime(res, (long)(filename), (long)(times)) -#define __sanitizer_syscall_pre_utimes(filename, utimes) \ +#define __sanitizer_syscall_pre_utimes(filename, utimes) \ __sanitizer_syscall_pre_impl_utimes((long)(filename), (long)(utimes)) -#define __sanitizer_syscall_post_utimes(res, filename, utimes) \ +#define __sanitizer_syscall_post_utimes(res, filename, utimes) \ __sanitizer_syscall_post_impl_utimes(res, (long)(filename), (long)(utimes)) -#define __sanitizer_syscall_pre_lseek(fd, offset, origin) \ +#define __sanitizer_syscall_pre_lseek(fd, offset, origin) \ __sanitizer_syscall_pre_impl_lseek((long)(fd), (long)(offset), (long)(origin)) -#define __sanitizer_syscall_post_lseek(res, fd, offset, origin) \ - __sanitizer_syscall_post_impl_lseek(res, (long)(fd), (long)(offset), \ +#define __sanitizer_syscall_post_lseek(res, fd, offset, origin) \ + __sanitizer_syscall_post_impl_lseek(res, (long)(fd), (long)(offset), \ (long)(origin)) -#define __sanitizer_syscall_pre_llseek(fd, offset_high, offset_low, result, \ - origin) \ - __sanitizer_syscall_pre_impl_llseek((long)(fd), (long)(offset_high), \ - (long)(offset_low), (long)(result), \ +#define __sanitizer_syscall_pre_llseek(fd, offset_high, offset_low, result, \ + origin) \ + __sanitizer_syscall_pre_impl_llseek((long)(fd), (long)(offset_high), \ + (long)(offset_low), (long)(result), \ (long)(origin)) -#define __sanitizer_syscall_post_llseek(res, fd, offset_high, offset_low, \ - result, origin) \ - __sanitizer_syscall_post_impl_llseek(res, (long)(fd), (long)(offset_high), \ - (long)(offset_low), (long)(result), \ +#define __sanitizer_syscall_post_llseek(res, fd, offset_high, offset_low, \ + result, origin) \ + __sanitizer_syscall_post_impl_llseek(res, (long)(fd), (long)(offset_high), \ + (long)(offset_low), (long)(result), \ (long)(origin)) -#define __sanitizer_syscall_pre_read(fd, buf, count) \ +#define __sanitizer_syscall_pre_read(fd, buf, count) \ __sanitizer_syscall_pre_impl_read((long)(fd), (long)(buf), (long)(count)) -#define __sanitizer_syscall_post_read(res, fd, buf, count) \ - __sanitizer_syscall_post_impl_read(res, (long)(fd), (long)(buf), \ +#define __sanitizer_syscall_post_read(res, fd, buf, count) \ + __sanitizer_syscall_post_impl_read(res, (long)(fd), (long)(buf), \ (long)(count)) -#define __sanitizer_syscall_pre_readv(fd, vec, vlen) \ +#define __sanitizer_syscall_pre_readv(fd, vec, vlen) \ __sanitizer_syscall_pre_impl_readv((long)(fd), (long)(vec), (long)(vlen)) -#define __sanitizer_syscall_post_readv(res, fd, vec, vlen) \ - __sanitizer_syscall_post_impl_readv(res, (long)(fd), (long)(vec), \ +#define __sanitizer_syscall_post_readv(res, fd, vec, vlen) \ + __sanitizer_syscall_post_impl_readv(res, (long)(fd), (long)(vec), \ (long)(vlen)) -#define __sanitizer_syscall_pre_write(fd, buf, count) \ +#define __sanitizer_syscall_pre_write(fd, buf, count) \ __sanitizer_syscall_pre_impl_write((long)(fd), (long)(buf), (long)(count)) -#define __sanitizer_syscall_post_write(res, fd, buf, count) \ - __sanitizer_syscall_post_impl_write(res, (long)(fd), (long)(buf), \ +#define __sanitizer_syscall_post_write(res, fd, buf, count) \ + __sanitizer_syscall_post_impl_write(res, (long)(fd), (long)(buf), \ (long)(count)) -#define __sanitizer_syscall_pre_writev(fd, vec, vlen) \ +#define __sanitizer_syscall_pre_writev(fd, vec, vlen) \ __sanitizer_syscall_pre_impl_writev((long)(fd), (long)(vec), (long)(vlen)) -#define __sanitizer_syscall_post_writev(res, fd, vec, vlen) \ - __sanitizer_syscall_post_impl_writev(res, (long)(fd), (long)(vec), \ +#define __sanitizer_syscall_post_writev(res, fd, vec, vlen) \ + __sanitizer_syscall_post_impl_writev(res, (long)(fd), (long)(vec), \ (long)(vlen)) #ifdef _LP64 #define __sanitizer_syscall_pre_pread64(fd, buf, count, pos) \ __sanitizer_syscall_pre_impl_pread64((long)(fd), (long)(buf), (long)(count), \ (long)(pos)) -#define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos) \ - __sanitizer_syscall_post_impl_pread64(res, (long)(fd), (long)(buf), \ +#define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos) \ + __sanitizer_syscall_post_impl_pread64(res, (long)(fd), (long)(buf), \ (long)(count), (long)(pos)) -#define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos) \ - __sanitizer_syscall_pre_impl_pwrite64((long)(fd), (long)(buf), \ +#define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos) \ + __sanitizer_syscall_pre_impl_pwrite64((long)(fd), (long)(buf), \ (long)(count), (long)(pos)) -#define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos) \ - __sanitizer_syscall_post_impl_pwrite64(res, (long)(fd), (long)(buf), \ +#define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos) \ + __sanitizer_syscall_post_impl_pwrite64(res, (long)(fd), (long)(buf), \ (long)(count), (long)(pos)) #else #define __sanitizer_syscall_pre_pread64(fd, buf, count, pos0, pos1) \ __sanitizer_syscall_pre_impl_pread64((long)(fd), (long)(buf), (long)(count), \ (long)(pos0), (long)(pos1)) -#define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos0, pos1) \ - __sanitizer_syscall_post_impl_pread64(res, (long)(fd), (long)(buf), \ - (long)(count), (long)(pos0), \ - (long)(pos1)) -#define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos0, pos1) \ - __sanitizer_syscall_pre_impl_pwrite64( \ +#define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos0, pos1) \ + __sanitizer_syscall_post_impl_pread64( \ + res, (long)(fd), (long)(buf), (long)(count), (long)(pos0), (long)(pos1)) +#define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos0, pos1) \ + __sanitizer_syscall_pre_impl_pwrite64( \ (long)(fd), (long)(buf), (long)(count), (long)(pos0), (long)(pos1)) -#define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos0, pos1) \ - __sanitizer_syscall_post_impl_pwrite64( \ +#define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos0, pos1) \ + __sanitizer_syscall_post_impl_pwrite64( \ res, (long)(fd), (long)(buf), (long)(count), (long)(pos0), (long)(pos1)) #endif -#define __sanitizer_syscall_pre_preadv(fd, vec, vlen, pos_l, pos_h) \ - __sanitizer_syscall_pre_impl_preadv((long)(fd), (long)(vec), (long)(vlen), \ +#define __sanitizer_syscall_pre_preadv(fd, vec, vlen, pos_l, pos_h) \ + __sanitizer_syscall_pre_impl_preadv((long)(fd), (long)(vec), (long)(vlen), \ (long)(pos_l), (long)(pos_h)) -#define __sanitizer_syscall_post_preadv(res, fd, vec, vlen, pos_l, pos_h) \ - __sanitizer_syscall_post_impl_preadv(res, (long)(fd), (long)(vec), \ - (long)(vlen), (long)(pos_l), \ +#define __sanitizer_syscall_post_preadv(res, fd, vec, vlen, pos_l, pos_h) \ + __sanitizer_syscall_post_impl_preadv(res, (long)(fd), (long)(vec), \ + (long)(vlen), (long)(pos_l), \ (long)(pos_h)) -#define __sanitizer_syscall_pre_pwritev(fd, vec, vlen, pos_l, pos_h) \ - __sanitizer_syscall_pre_impl_pwritev((long)(fd), (long)(vec), (long)(vlen), \ +#define __sanitizer_syscall_pre_pwritev(fd, vec, vlen, pos_l, pos_h) \ + __sanitizer_syscall_pre_impl_pwritev((long)(fd), (long)(vec), (long)(vlen), \ (long)(pos_l), (long)(pos_h)) -#define __sanitizer_syscall_post_pwritev(res, fd, vec, vlen, pos_l, pos_h) \ - __sanitizer_syscall_post_impl_pwritev(res, (long)(fd), (long)(vec), \ - (long)(vlen), (long)(pos_l), \ +#define __sanitizer_syscall_post_pwritev(res, fd, vec, vlen, pos_l, pos_h) \ + __sanitizer_syscall_post_impl_pwritev(res, (long)(fd), (long)(vec), \ + (long)(vlen), (long)(pos_l), \ (long)(pos_h)) -#define __sanitizer_syscall_pre_getcwd(buf, size) \ +#define __sanitizer_syscall_pre_getcwd(buf, size) \ __sanitizer_syscall_pre_impl_getcwd((long)(buf), (long)(size)) -#define __sanitizer_syscall_post_getcwd(res, buf, size) \ +#define __sanitizer_syscall_post_getcwd(res, buf, size) \ __sanitizer_syscall_post_impl_getcwd(res, (long)(buf), (long)(size)) -#define __sanitizer_syscall_pre_mkdir(pathname, mode) \ +#define __sanitizer_syscall_pre_mkdir(pathname, mode) \ __sanitizer_syscall_pre_impl_mkdir((long)(pathname), (long)(mode)) -#define __sanitizer_syscall_post_mkdir(res, pathname, mode) \ +#define __sanitizer_syscall_post_mkdir(res, pathname, mode) \ __sanitizer_syscall_post_impl_mkdir(res, (long)(pathname), (long)(mode)) -#define __sanitizer_syscall_pre_chdir(filename) \ +#define __sanitizer_syscall_pre_chdir(filename) \ __sanitizer_syscall_pre_impl_chdir((long)(filename)) -#define __sanitizer_syscall_post_chdir(res, filename) \ +#define __sanitizer_syscall_post_chdir(res, filename) \ __sanitizer_syscall_post_impl_chdir(res, (long)(filename)) -#define __sanitizer_syscall_pre_fchdir(fd) \ +#define __sanitizer_syscall_pre_fchdir(fd) \ __sanitizer_syscall_pre_impl_fchdir((long)(fd)) -#define __sanitizer_syscall_post_fchdir(res, fd) \ +#define __sanitizer_syscall_post_fchdir(res, fd) \ __sanitizer_syscall_post_impl_fchdir(res, (long)(fd)) -#define __sanitizer_syscall_pre_rmdir(pathname) \ +#define __sanitizer_syscall_pre_rmdir(pathname) \ __sanitizer_syscall_pre_impl_rmdir((long)(pathname)) -#define __sanitizer_syscall_post_rmdir(res, pathname) \ +#define __sanitizer_syscall_post_rmdir(res, pathname) \ __sanitizer_syscall_post_impl_rmdir(res, (long)(pathname)) -#define __sanitizer_syscall_pre_lookup_dcookie(cookie64, buf, len) \ - __sanitizer_syscall_pre_impl_lookup_dcookie((long)(cookie64), (long)(buf), \ +#define __sanitizer_syscall_pre_lookup_dcookie(cookie64, buf, len) \ + __sanitizer_syscall_pre_impl_lookup_dcookie((long)(cookie64), (long)(buf), \ (long)(len)) -#define __sanitizer_syscall_post_lookup_dcookie(res, cookie64, buf, len) \ - __sanitizer_syscall_post_impl_lookup_dcookie(res, (long)(cookie64), \ +#define __sanitizer_syscall_post_lookup_dcookie(res, cookie64, buf, len) \ + __sanitizer_syscall_post_impl_lookup_dcookie(res, (long)(cookie64), \ (long)(buf), (long)(len)) -#define __sanitizer_syscall_pre_quotactl(cmd, special, id, addr) \ - __sanitizer_syscall_pre_impl_quotactl((long)(cmd), (long)(special), \ +#define __sanitizer_syscall_pre_quotactl(cmd, special, id, addr) \ + __sanitizer_syscall_pre_impl_quotactl((long)(cmd), (long)(special), \ (long)(id), (long)(addr)) -#define __sanitizer_syscall_post_quotactl(res, cmd, special, id, addr) \ - __sanitizer_syscall_post_impl_quotactl(res, (long)(cmd), (long)(special), \ +#define __sanitizer_syscall_post_quotactl(res, cmd, special, id, addr) \ + __sanitizer_syscall_post_impl_quotactl(res, (long)(cmd), (long)(special), \ (long)(id), (long)(addr)) -#define __sanitizer_syscall_pre_getdents(fd, dirent, count) \ - __sanitizer_syscall_pre_impl_getdents((long)(fd), (long)(dirent), \ +#define __sanitizer_syscall_pre_getdents(fd, dirent, count) \ + __sanitizer_syscall_pre_impl_getdents((long)(fd), (long)(dirent), \ (long)(count)) -#define __sanitizer_syscall_post_getdents(res, fd, dirent, count) \ - __sanitizer_syscall_post_impl_getdents(res, (long)(fd), (long)(dirent), \ +#define __sanitizer_syscall_post_getdents(res, fd, dirent, count) \ + __sanitizer_syscall_post_impl_getdents(res, (long)(fd), (long)(dirent), \ (long)(count)) -#define __sanitizer_syscall_pre_getdents64(fd, dirent, count) \ - __sanitizer_syscall_pre_impl_getdents64((long)(fd), (long)(dirent), \ +#define __sanitizer_syscall_pre_getdents64(fd, dirent, count) \ + __sanitizer_syscall_pre_impl_getdents64((long)(fd), (long)(dirent), \ (long)(count)) -#define __sanitizer_syscall_post_getdents64(res, fd, dirent, count) \ - __sanitizer_syscall_post_impl_getdents64(res, (long)(fd), (long)(dirent), \ +#define __sanitizer_syscall_post_getdents64(res, fd, dirent, count) \ + __sanitizer_syscall_post_impl_getdents64(res, (long)(fd), (long)(dirent), \ (long)(count)) #define __sanitizer_syscall_pre_setsockopt(fd, level, optname, optval, optlen) \ __sanitizer_syscall_pre_impl_setsockopt((long)(fd), (long)(level), \ (long)(optname), (long)(optval), \ (long)(optlen)) -#define __sanitizer_syscall_post_setsockopt(res, fd, level, optname, optval, \ - optlen) \ - __sanitizer_syscall_post_impl_setsockopt(res, (long)(fd), (long)(level), \ - (long)(optname), (long)(optval), \ +#define __sanitizer_syscall_post_setsockopt(res, fd, level, optname, optval, \ + optlen) \ + __sanitizer_syscall_post_impl_setsockopt(res, (long)(fd), (long)(level), \ + (long)(optname), (long)(optval), \ (long)(optlen)) #define __sanitizer_syscall_pre_getsockopt(fd, level, optname, optval, optlen) \ __sanitizer_syscall_pre_impl_getsockopt((long)(fd), (long)(level), \ (long)(optname), (long)(optval), \ (long)(optlen)) -#define __sanitizer_syscall_post_getsockopt(res, fd, level, optname, optval, \ - optlen) \ - __sanitizer_syscall_post_impl_getsockopt(res, (long)(fd), (long)(level), \ - (long)(optname), (long)(optval), \ +#define __sanitizer_syscall_post_getsockopt(res, fd, level, optname, optval, \ + optlen) \ + __sanitizer_syscall_post_impl_getsockopt(res, (long)(fd), (long)(level), \ + (long)(optname), (long)(optval), \ (long)(optlen)) -#define __sanitizer_syscall_pre_bind(arg0, arg1, arg2) \ +#define __sanitizer_syscall_pre_bind(arg0, arg1, arg2) \ __sanitizer_syscall_pre_impl_bind((long)(arg0), (long)(arg1), (long)(arg2)) -#define __sanitizer_syscall_post_bind(res, arg0, arg1, arg2) \ - __sanitizer_syscall_post_impl_bind(res, (long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_post_bind(res, arg0, arg1, arg2) \ + __sanitizer_syscall_post_impl_bind(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) -#define __sanitizer_syscall_pre_connect(arg0, arg1, arg2) \ +#define __sanitizer_syscall_pre_connect(arg0, arg1, arg2) \ __sanitizer_syscall_pre_impl_connect((long)(arg0), (long)(arg1), (long)(arg2)) -#define __sanitizer_syscall_post_connect(res, arg0, arg1, arg2) \ - __sanitizer_syscall_post_impl_connect(res, (long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_post_connect(res, arg0, arg1, arg2) \ + __sanitizer_syscall_post_impl_connect(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) -#define __sanitizer_syscall_pre_accept(arg0, arg1, arg2) \ +#define __sanitizer_syscall_pre_accept(arg0, arg1, arg2) \ __sanitizer_syscall_pre_impl_accept((long)(arg0), (long)(arg1), (long)(arg2)) -#define __sanitizer_syscall_post_accept(res, arg0, arg1, arg2) \ - __sanitizer_syscall_post_impl_accept(res, (long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_post_accept(res, arg0, arg1, arg2) \ + __sanitizer_syscall_post_impl_accept(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) -#define __sanitizer_syscall_pre_accept4(arg0, arg1, arg2, arg3) \ - __sanitizer_syscall_pre_impl_accept4((long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_pre_accept4(arg0, arg1, arg2, arg3) \ + __sanitizer_syscall_pre_impl_accept4((long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3)) -#define __sanitizer_syscall_post_accept4(res, arg0, arg1, arg2, arg3) \ - __sanitizer_syscall_post_impl_accept4(res, (long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_post_accept4(res, arg0, arg1, arg2, arg3) \ + __sanitizer_syscall_post_impl_accept4(res, (long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3)) -#define __sanitizer_syscall_pre_getsockname(arg0, arg1, arg2) \ - __sanitizer_syscall_pre_impl_getsockname((long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_pre_getsockname(arg0, arg1, arg2) \ + __sanitizer_syscall_pre_impl_getsockname((long)(arg0), (long)(arg1), \ (long)(arg2)) -#define __sanitizer_syscall_post_getsockname(res, arg0, arg1, arg2) \ - __sanitizer_syscall_post_impl_getsockname(res, (long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_post_getsockname(res, arg0, arg1, arg2) \ + __sanitizer_syscall_post_impl_getsockname(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) -#define __sanitizer_syscall_pre_getpeername(arg0, arg1, arg2) \ - __sanitizer_syscall_pre_impl_getpeername((long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_pre_getpeername(arg0, arg1, arg2) \ + __sanitizer_syscall_pre_impl_getpeername((long)(arg0), (long)(arg1), \ (long)(arg2)) -#define __sanitizer_syscall_post_getpeername(res, arg0, arg1, arg2) \ - __sanitizer_syscall_post_impl_getpeername(res, (long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_post_getpeername(res, arg0, arg1, arg2) \ + __sanitizer_syscall_post_impl_getpeername(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) -#define __sanitizer_syscall_pre_send(arg0, arg1, arg2, arg3) \ - __sanitizer_syscall_pre_impl_send((long)(arg0), (long)(arg1), (long)(arg2), \ +#define __sanitizer_syscall_pre_send(arg0, arg1, arg2, arg3) \ + __sanitizer_syscall_pre_impl_send((long)(arg0), (long)(arg1), (long)(arg2), \ (long)(arg3)) -#define __sanitizer_syscall_post_send(res, arg0, arg1, arg2, arg3) \ - __sanitizer_syscall_post_impl_send(res, (long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_post_send(res, arg0, arg1, arg2, arg3) \ + __sanitizer_syscall_post_impl_send(res, (long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3)) -#define __sanitizer_syscall_pre_sendto(arg0, arg1, arg2, arg3, arg4, arg5) \ - __sanitizer_syscall_pre_impl_sendto((long)(arg0), (long)(arg1), \ - (long)(arg2), (long)(arg3), \ +#define __sanitizer_syscall_pre_sendto(arg0, arg1, arg2, arg3, arg4, arg5) \ + __sanitizer_syscall_pre_impl_sendto((long)(arg0), (long)(arg1), \ + (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) -#define __sanitizer_syscall_post_sendto(res, arg0, arg1, arg2, arg3, arg4, \ - arg5) \ - __sanitizer_syscall_post_impl_sendto(res, (long)(arg0), (long)(arg1), \ - (long)(arg2), (long)(arg3), \ +#define __sanitizer_syscall_post_sendto(res, arg0, arg1, arg2, arg3, arg4, \ + arg5) \ + __sanitizer_syscall_post_impl_sendto(res, (long)(arg0), (long)(arg1), \ + (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) -#define __sanitizer_syscall_pre_sendmsg(fd, msg, flags) \ +#define __sanitizer_syscall_pre_sendmsg(fd, msg, flags) \ __sanitizer_syscall_pre_impl_sendmsg((long)(fd), (long)(msg), (long)(flags)) -#define __sanitizer_syscall_post_sendmsg(res, fd, msg, flags) \ - __sanitizer_syscall_post_impl_sendmsg(res, (long)(fd), (long)(msg), \ +#define __sanitizer_syscall_post_sendmsg(res, fd, msg, flags) \ + __sanitizer_syscall_post_impl_sendmsg(res, (long)(fd), (long)(msg), \ (long)(flags)) #define __sanitizer_syscall_pre_sendmmsg(fd, msg, vlen, flags) \ __sanitizer_syscall_pre_impl_sendmmsg((long)(fd), (long)(msg), (long)(vlen), \ (long)(flags)) -#define __sanitizer_syscall_post_sendmmsg(res, fd, msg, vlen, flags) \ - __sanitizer_syscall_post_impl_sendmmsg(res, (long)(fd), (long)(msg), \ +#define __sanitizer_syscall_post_sendmmsg(res, fd, msg, vlen, flags) \ + __sanitizer_syscall_post_impl_sendmmsg(res, (long)(fd), (long)(msg), \ (long)(vlen), (long)(flags)) -#define __sanitizer_syscall_pre_recv(arg0, arg1, arg2, arg3) \ - __sanitizer_syscall_pre_impl_recv((long)(arg0), (long)(arg1), (long)(arg2), \ +#define __sanitizer_syscall_pre_recv(arg0, arg1, arg2, arg3) \ + __sanitizer_syscall_pre_impl_recv((long)(arg0), (long)(arg1), (long)(arg2), \ (long)(arg3)) -#define __sanitizer_syscall_post_recv(res, arg0, arg1, arg2, arg3) \ - __sanitizer_syscall_post_impl_recv(res, (long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_post_recv(res, arg0, arg1, arg2, arg3) \ + __sanitizer_syscall_post_impl_recv(res, (long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3)) -#define __sanitizer_syscall_pre_recvfrom(arg0, arg1, arg2, arg3, arg4, arg5) \ - __sanitizer_syscall_pre_impl_recvfrom((long)(arg0), (long)(arg1), \ - (long)(arg2), (long)(arg3), \ +#define __sanitizer_syscall_pre_recvfrom(arg0, arg1, arg2, arg3, arg4, arg5) \ + __sanitizer_syscall_pre_impl_recvfrom((long)(arg0), (long)(arg1), \ + (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) -#define __sanitizer_syscall_post_recvfrom(res, arg0, arg1, arg2, arg3, arg4, \ - arg5) \ - __sanitizer_syscall_post_impl_recvfrom(res, (long)(arg0), (long)(arg1), \ - (long)(arg2), (long)(arg3), \ +#define __sanitizer_syscall_post_recvfrom(res, arg0, arg1, arg2, arg3, arg4, \ + arg5) \ + __sanitizer_syscall_post_impl_recvfrom(res, (long)(arg0), (long)(arg1), \ + (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) -#define __sanitizer_syscall_pre_recvmsg(fd, msg, flags) \ +#define __sanitizer_syscall_pre_recvmsg(fd, msg, flags) \ __sanitizer_syscall_pre_impl_recvmsg((long)(fd), (long)(msg), (long)(flags)) -#define __sanitizer_syscall_post_recvmsg(res, fd, msg, flags) \ - __sanitizer_syscall_post_impl_recvmsg(res, (long)(fd), (long)(msg), \ +#define __sanitizer_syscall_post_recvmsg(res, fd, msg, flags) \ + __sanitizer_syscall_post_impl_recvmsg(res, (long)(fd), (long)(msg), \ (long)(flags)) #define __sanitizer_syscall_pre_recvmmsg(fd, msg, vlen, flags, timeout) \ __sanitizer_syscall_pre_impl_recvmmsg((long)(fd), (long)(msg), (long)(vlen), \ (long)(flags), (long)(timeout)) -#define __sanitizer_syscall_post_recvmmsg(res, fd, msg, vlen, flags, timeout) \ - __sanitizer_syscall_post_impl_recvmmsg(res, (long)(fd), (long)(msg), \ - (long)(vlen), (long)(flags), \ +#define __sanitizer_syscall_post_recvmmsg(res, fd, msg, vlen, flags, timeout) \ + __sanitizer_syscall_post_impl_recvmmsg(res, (long)(fd), (long)(msg), \ + (long)(vlen), (long)(flags), \ (long)(timeout)) -#define __sanitizer_syscall_pre_socket(arg0, arg1, arg2) \ +#define __sanitizer_syscall_pre_socket(arg0, arg1, arg2) \ __sanitizer_syscall_pre_impl_socket((long)(arg0), (long)(arg1), (long)(arg2)) -#define __sanitizer_syscall_post_socket(res, arg0, arg1, arg2) \ - __sanitizer_syscall_post_impl_socket(res, (long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_post_socket(res, arg0, arg1, arg2) \ + __sanitizer_syscall_post_impl_socket(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) -#define __sanitizer_syscall_pre_socketpair(arg0, arg1, arg2, arg3) \ - __sanitizer_syscall_pre_impl_socketpair((long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_pre_socketpair(arg0, arg1, arg2, arg3) \ + __sanitizer_syscall_pre_impl_socketpair((long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3)) -#define __sanitizer_syscall_post_socketpair(res, arg0, arg1, arg2, arg3) \ - __sanitizer_syscall_post_impl_socketpair(res, (long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_post_socketpair(res, arg0, arg1, arg2, arg3) \ + __sanitizer_syscall_post_impl_socketpair(res, (long)(arg0), (long)(arg1), \ (long)(arg2), (long)(arg3)) -#define __sanitizer_syscall_pre_socketcall(call, args) \ +#define __sanitizer_syscall_pre_socketcall(call, args) \ __sanitizer_syscall_pre_impl_socketcall((long)(call), (long)(args)) -#define __sanitizer_syscall_post_socketcall(res, call, args) \ +#define __sanitizer_syscall_post_socketcall(res, call, args) \ __sanitizer_syscall_post_impl_socketcall(res, (long)(call), (long)(args)) -#define __sanitizer_syscall_pre_listen(arg0, arg1) \ +#define __sanitizer_syscall_pre_listen(arg0, arg1) \ __sanitizer_syscall_pre_impl_listen((long)(arg0), (long)(arg1)) -#define __sanitizer_syscall_post_listen(res, arg0, arg1) \ +#define __sanitizer_syscall_post_listen(res, arg0, arg1) \ __sanitizer_syscall_post_impl_listen(res, (long)(arg0), (long)(arg1)) -#define __sanitizer_syscall_pre_poll(ufds, nfds, timeout) \ +#define __sanitizer_syscall_pre_poll(ufds, nfds, timeout) \ __sanitizer_syscall_pre_impl_poll((long)(ufds), (long)(nfds), (long)(timeout)) -#define __sanitizer_syscall_post_poll(res, ufds, nfds, timeout) \ - __sanitizer_syscall_post_impl_poll(res, (long)(ufds), (long)(nfds), \ +#define __sanitizer_syscall_post_poll(res, ufds, nfds, timeout) \ + __sanitizer_syscall_post_impl_poll(res, (long)(ufds), (long)(nfds), \ (long)(timeout)) -#define __sanitizer_syscall_pre_select(n, inp, outp, exp, tvp) \ - __sanitizer_syscall_pre_impl_select((long)(n), (long)(inp), (long)(outp), \ +#define __sanitizer_syscall_pre_select(n, inp, outp, exp, tvp) \ + __sanitizer_syscall_pre_impl_select((long)(n), (long)(inp), (long)(outp), \ (long)(exp), (long)(tvp)) -#define __sanitizer_syscall_post_select(res, n, inp, outp, exp, tvp) \ - __sanitizer_syscall_post_impl_select(res, (long)(n), (long)(inp), \ +#define __sanitizer_syscall_post_select(res, n, inp, outp, exp, tvp) \ + __sanitizer_syscall_post_impl_select(res, (long)(n), (long)(inp), \ (long)(outp), (long)(exp), (long)(tvp)) -#define __sanitizer_syscall_pre_old_select(arg) \ +#define __sanitizer_syscall_pre_old_select(arg) \ __sanitizer_syscall_pre_impl_old_select((long)(arg)) -#define __sanitizer_syscall_post_old_select(res, arg) \ +#define __sanitizer_syscall_post_old_select(res, arg) \ __sanitizer_syscall_post_impl_old_select(res, (long)(arg)) -#define __sanitizer_syscall_pre_epoll_create(size) \ +#define __sanitizer_syscall_pre_epoll_create(size) \ __sanitizer_syscall_pre_impl_epoll_create((long)(size)) -#define __sanitizer_syscall_post_epoll_create(res, size) \ +#define __sanitizer_syscall_post_epoll_create(res, size) \ __sanitizer_syscall_post_impl_epoll_create(res, (long)(size)) -#define __sanitizer_syscall_pre_epoll_create1(flags) \ +#define __sanitizer_syscall_pre_epoll_create1(flags) \ __sanitizer_syscall_pre_impl_epoll_create1((long)(flags)) -#define __sanitizer_syscall_post_epoll_create1(res, flags) \ +#define __sanitizer_syscall_post_epoll_create1(res, flags) \ __sanitizer_syscall_post_impl_epoll_create1(res, (long)(flags)) #define __sanitizer_syscall_pre_epoll_ctl(epfd, op, fd, event) \ __sanitizer_syscall_pre_impl_epoll_ctl((long)(epfd), (long)(op), (long)(fd), \ (long)(event)) -#define __sanitizer_syscall_post_epoll_ctl(res, epfd, op, fd, event) \ - __sanitizer_syscall_post_impl_epoll_ctl(res, (long)(epfd), (long)(op), \ +#define __sanitizer_syscall_post_epoll_ctl(res, epfd, op, fd, event) \ + __sanitizer_syscall_post_impl_epoll_ctl(res, (long)(epfd), (long)(op), \ (long)(fd), (long)(event)) -#define __sanitizer_syscall_pre_epoll_wait(epfd, events, maxevents, timeout) \ - __sanitizer_syscall_pre_impl_epoll_wait((long)(epfd), (long)(events), \ +#define __sanitizer_syscall_pre_epoll_wait(epfd, events, maxevents, timeout) \ + __sanitizer_syscall_pre_impl_epoll_wait((long)(epfd), (long)(events), \ (long)(maxevents), (long)(timeout)) -#define __sanitizer_syscall_post_epoll_wait(res, epfd, events, maxevents, \ - timeout) \ - __sanitizer_syscall_post_impl_epoll_wait(res, (long)(epfd), (long)(events), \ +#define __sanitizer_syscall_post_epoll_wait(res, epfd, events, maxevents, \ + timeout) \ + __sanitizer_syscall_post_impl_epoll_wait(res, (long)(epfd), (long)(events), \ (long)(maxevents), (long)(timeout)) -#define __sanitizer_syscall_pre_epoll_pwait(epfd, events, maxevents, timeout, \ - sigmask, sigsetsize) \ - __sanitizer_syscall_pre_impl_epoll_pwait( \ - (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \ +#define __sanitizer_syscall_pre_epoll_pwait(epfd, events, maxevents, timeout, \ + sigmask, sigsetsize) \ + __sanitizer_syscall_pre_impl_epoll_pwait( \ + (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \ + (long)(sigmask), (long)(sigsetsize)) +#define __sanitizer_syscall_post_epoll_pwait(res, epfd, events, maxevents, \ + timeout, sigmask, sigsetsize) \ + __sanitizer_syscall_post_impl_epoll_pwait( \ + res, (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \ (long)(sigmask), (long)(sigsetsize)) -#define __sanitizer_syscall_post_epoll_pwait(res, epfd, events, maxevents, \ - timeout, sigmask, sigsetsize) \ - __sanitizer_syscall_post_impl_epoll_pwait( \ - res, (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \ +#define __sanitizer_syscall_pre_epoll_pwait2(epfd, events, maxevents, timeout, \ + sigmask, sigsetsize) \ + __sanitizer_syscall_pre_impl_epoll_pwait2( \ + (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \ (long)(sigmask), (long)(sigsetsize)) -#define __sanitizer_syscall_pre_gethostname(name, len) \ +#define __sanitizer_syscall_post_epoll_pwait2(res, epfd, events, maxevents, \ + timeout, sigmask, sigsetsize) \ + __sanitizer_syscall_post_impl_epoll_pwait2( \ + res, (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \ + (long)(sigmask), (long)(sigsetsize)) +#define __sanitizer_syscall_pre_gethostname(name, len) \ __sanitizer_syscall_pre_impl_gethostname((long)(name), (long)(len)) -#define __sanitizer_syscall_post_gethostname(res, name, len) \ +#define __sanitizer_syscall_post_gethostname(res, name, len) \ __sanitizer_syscall_post_impl_gethostname(res, (long)(name), (long)(len)) -#define __sanitizer_syscall_pre_sethostname(name, len) \ +#define __sanitizer_syscall_pre_sethostname(name, len) \ __sanitizer_syscall_pre_impl_sethostname((long)(name), (long)(len)) -#define __sanitizer_syscall_post_sethostname(res, name, len) \ +#define __sanitizer_syscall_post_sethostname(res, name, len) \ __sanitizer_syscall_post_impl_sethostname(res, (long)(name), (long)(len)) -#define __sanitizer_syscall_pre_setdomainname(name, len) \ +#define __sanitizer_syscall_pre_setdomainname(name, len) \ __sanitizer_syscall_pre_impl_setdomainname((long)(name), (long)(len)) -#define __sanitizer_syscall_post_setdomainname(res, name, len) \ +#define __sanitizer_syscall_post_setdomainname(res, name, len) \ __sanitizer_syscall_post_impl_setdomainname(res, (long)(name), (long)(len)) -#define __sanitizer_syscall_pre_newuname(name) \ +#define __sanitizer_syscall_pre_newuname(name) \ __sanitizer_syscall_pre_impl_newuname((long)(name)) -#define __sanitizer_syscall_post_newuname(res, name) \ +#define __sanitizer_syscall_post_newuname(res, name) \ __sanitizer_syscall_post_impl_newuname(res, (long)(name)) -#define __sanitizer_syscall_pre_uname(arg0) \ +#define __sanitizer_syscall_pre_uname(arg0) \ __sanitizer_syscall_pre_impl_uname((long)(arg0)) -#define __sanitizer_syscall_post_uname(res, arg0) \ +#define __sanitizer_syscall_post_uname(res, arg0) \ __sanitizer_syscall_post_impl_uname(res, (long)(arg0)) -#define __sanitizer_syscall_pre_olduname(arg0) \ +#define __sanitizer_syscall_pre_olduname(arg0) \ __sanitizer_syscall_pre_impl_olduname((long)(arg0)) -#define __sanitizer_syscall_post_olduname(res, arg0) \ +#define __sanitizer_syscall_post_olduname(res, arg0) \ __sanitizer_syscall_post_impl_olduname(res, (long)(arg0)) -#define __sanitizer_syscall_pre_getrlimit(resource, rlim) \ +#define __sanitizer_syscall_pre_getrlimit(resource, rlim) \ __sanitizer_syscall_pre_impl_getrlimit((long)(resource), (long)(rlim)) -#define __sanitizer_syscall_post_getrlimit(res, resource, rlim) \ +#define __sanitizer_syscall_post_getrlimit(res, resource, rlim) \ __sanitizer_syscall_post_impl_getrlimit(res, (long)(resource), (long)(rlim)) -#define __sanitizer_syscall_pre_old_getrlimit(resource, rlim) \ +#define __sanitizer_syscall_pre_old_getrlimit(resource, rlim) \ __sanitizer_syscall_pre_impl_old_getrlimit((long)(resource), (long)(rlim)) -#define __sanitizer_syscall_post_old_getrlimit(res, resource, rlim) \ - __sanitizer_syscall_post_impl_old_getrlimit(res, (long)(resource), \ +#define __sanitizer_syscall_post_old_getrlimit(res, resource, rlim) \ + __sanitizer_syscall_post_impl_old_getrlimit(res, (long)(resource), \ (long)(rlim)) -#define __sanitizer_syscall_pre_setrlimit(resource, rlim) \ +#define __sanitizer_syscall_pre_setrlimit(resource, rlim) \ __sanitizer_syscall_pre_impl_setrlimit((long)(resource), (long)(rlim)) -#define __sanitizer_syscall_post_setrlimit(res, resource, rlim) \ +#define __sanitizer_syscall_post_setrlimit(res, resource, rlim) \ __sanitizer_syscall_post_impl_setrlimit(res, (long)(resource), (long)(rlim)) -#define __sanitizer_syscall_pre_prlimit64(pid, resource, new_rlim, old_rlim) \ - __sanitizer_syscall_pre_impl_prlimit64((long)(pid), (long)(resource), \ +#define __sanitizer_syscall_pre_prlimit64(pid, resource, new_rlim, old_rlim) \ + __sanitizer_syscall_pre_impl_prlimit64((long)(pid), (long)(resource), \ (long)(new_rlim), (long)(old_rlim)) -#define __sanitizer_syscall_post_prlimit64(res, pid, resource, new_rlim, \ - old_rlim) \ - __sanitizer_syscall_post_impl_prlimit64(res, (long)(pid), (long)(resource), \ +#define __sanitizer_syscall_post_prlimit64(res, pid, resource, new_rlim, \ + old_rlim) \ + __sanitizer_syscall_post_impl_prlimit64(res, (long)(pid), (long)(resource), \ (long)(new_rlim), (long)(old_rlim)) -#define __sanitizer_syscall_pre_getrusage(who, ru) \ +#define __sanitizer_syscall_pre_getrusage(who, ru) \ __sanitizer_syscall_pre_impl_getrusage((long)(who), (long)(ru)) -#define __sanitizer_syscall_post_getrusage(res, who, ru) \ +#define __sanitizer_syscall_post_getrusage(res, who, ru) \ __sanitizer_syscall_post_impl_getrusage(res, (long)(who), (long)(ru)) -#define __sanitizer_syscall_pre_umask(mask) \ +#define __sanitizer_syscall_pre_umask(mask) \ __sanitizer_syscall_pre_impl_umask((long)(mask)) -#define __sanitizer_syscall_post_umask(res, mask) \ +#define __sanitizer_syscall_post_umask(res, mask) \ __sanitizer_syscall_post_impl_umask(res, (long)(mask)) -#define __sanitizer_syscall_pre_msgget(key, msgflg) \ +#define __sanitizer_syscall_pre_msgget(key, msgflg) \ __sanitizer_syscall_pre_impl_msgget((long)(key), (long)(msgflg)) -#define __sanitizer_syscall_post_msgget(res, key, msgflg) \ +#define __sanitizer_syscall_post_msgget(res, key, msgflg) \ __sanitizer_syscall_post_impl_msgget(res, (long)(key), (long)(msgflg)) -#define __sanitizer_syscall_pre_msgsnd(msqid, msgp, msgsz, msgflg) \ - __sanitizer_syscall_pre_impl_msgsnd((long)(msqid), (long)(msgp), \ +#define __sanitizer_syscall_pre_msgsnd(msqid, msgp, msgsz, msgflg) \ + __sanitizer_syscall_pre_impl_msgsnd((long)(msqid), (long)(msgp), \ (long)(msgsz), (long)(msgflg)) -#define __sanitizer_syscall_post_msgsnd(res, msqid, msgp, msgsz, msgflg) \ - __sanitizer_syscall_post_impl_msgsnd(res, (long)(msqid), (long)(msgp), \ +#define __sanitizer_syscall_post_msgsnd(res, msqid, msgp, msgsz, msgflg) \ + __sanitizer_syscall_post_impl_msgsnd(res, (long)(msqid), (long)(msgp), \ (long)(msgsz), (long)(msgflg)) -#define __sanitizer_syscall_pre_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) \ - __sanitizer_syscall_pre_impl_msgrcv((long)(msqid), (long)(msgp), \ - (long)(msgsz), (long)(msgtyp), \ +#define __sanitizer_syscall_pre_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) \ + __sanitizer_syscall_pre_impl_msgrcv((long)(msqid), (long)(msgp), \ + (long)(msgsz), (long)(msgtyp), \ (long)(msgflg)) -#define __sanitizer_syscall_post_msgrcv(res, msqid, msgp, msgsz, msgtyp, \ - msgflg) \ - __sanitizer_syscall_post_impl_msgrcv(res, (long)(msqid), (long)(msgp), \ - (long)(msgsz), (long)(msgtyp), \ +#define __sanitizer_syscall_post_msgrcv(res, msqid, msgp, msgsz, msgtyp, \ + msgflg) \ + __sanitizer_syscall_post_impl_msgrcv(res, (long)(msqid), (long)(msgp), \ + (long)(msgsz), (long)(msgtyp), \ (long)(msgflg)) -#define __sanitizer_syscall_pre_msgctl(msqid, cmd, buf) \ +#define __sanitizer_syscall_pre_msgctl(msqid, cmd, buf) \ __sanitizer_syscall_pre_impl_msgctl((long)(msqid), (long)(cmd), (long)(buf)) -#define __sanitizer_syscall_post_msgctl(res, msqid, cmd, buf) \ - __sanitizer_syscall_post_impl_msgctl(res, (long)(msqid), (long)(cmd), \ +#define __sanitizer_syscall_post_msgctl(res, msqid, cmd, buf) \ + __sanitizer_syscall_post_impl_msgctl(res, (long)(msqid), (long)(cmd), \ (long)(buf)) -#define __sanitizer_syscall_pre_semget(key, nsems, semflg) \ - __sanitizer_syscall_pre_impl_semget((long)(key), (long)(nsems), \ +#define __sanitizer_syscall_pre_semget(key, nsems, semflg) \ + __sanitizer_syscall_pre_impl_semget((long)(key), (long)(nsems), \ (long)(semflg)) -#define __sanitizer_syscall_post_semget(res, key, nsems, semflg) \ - __sanitizer_syscall_post_impl_semget(res, (long)(key), (long)(nsems), \ +#define __sanitizer_syscall_post_semget(res, key, nsems, semflg) \ + __sanitizer_syscall_post_impl_semget(res, (long)(key), (long)(nsems), \ (long)(semflg)) -#define __sanitizer_syscall_pre_semop(semid, sops, nsops) \ +#define __sanitizer_syscall_pre_semop(semid, sops, nsops) \ __sanitizer_syscall_pre_impl_semop((long)(semid), (long)(sops), (long)(nsops)) -#define __sanitizer_syscall_post_semop(res, semid, sops, nsops) \ - __sanitizer_syscall_post_impl_semop(res, (long)(semid), (long)(sops), \ +#define __sanitizer_syscall_post_semop(res, semid, sops, nsops) \ + __sanitizer_syscall_post_impl_semop(res, (long)(semid), (long)(sops), \ (long)(nsops)) -#define __sanitizer_syscall_pre_semctl(semid, semnum, cmd, arg) \ - __sanitizer_syscall_pre_impl_semctl((long)(semid), (long)(semnum), \ +#define __sanitizer_syscall_pre_semctl(semid, semnum, cmd, arg) \ + __sanitizer_syscall_pre_impl_semctl((long)(semid), (long)(semnum), \ (long)(cmd), (long)(arg)) -#define __sanitizer_syscall_post_semctl(res, semid, semnum, cmd, arg) \ - __sanitizer_syscall_post_impl_semctl(res, (long)(semid), (long)(semnum), \ +#define __sanitizer_syscall_post_semctl(res, semid, semnum, cmd, arg) \ + __sanitizer_syscall_post_impl_semctl(res, (long)(semid), (long)(semnum), \ (long)(cmd), (long)(arg)) -#define __sanitizer_syscall_pre_semtimedop(semid, sops, nsops, timeout) \ - __sanitizer_syscall_pre_impl_semtimedop((long)(semid), (long)(sops), \ +#define __sanitizer_syscall_pre_semtimedop(semid, sops, nsops, timeout) \ + __sanitizer_syscall_pre_impl_semtimedop((long)(semid), (long)(sops), \ (long)(nsops), (long)(timeout)) -#define __sanitizer_syscall_post_semtimedop(res, semid, sops, nsops, timeout) \ - __sanitizer_syscall_post_impl_semtimedop(res, (long)(semid), (long)(sops), \ +#define __sanitizer_syscall_post_semtimedop(res, semid, sops, nsops, timeout) \ + __sanitizer_syscall_post_impl_semtimedop(res, (long)(semid), (long)(sops), \ (long)(nsops), (long)(timeout)) -#define __sanitizer_syscall_pre_shmat(shmid, shmaddr, shmflg) \ - __sanitizer_syscall_pre_impl_shmat((long)(shmid), (long)(shmaddr), \ +#define __sanitizer_syscall_pre_shmat(shmid, shmaddr, shmflg) \ + __sanitizer_syscall_pre_impl_shmat((long)(shmid), (long)(shmaddr), \ (long)(shmflg)) -#define __sanitizer_syscall_post_shmat(res, shmid, shmaddr, shmflg) \ - __sanitizer_syscall_post_impl_shmat(res, (long)(shmid), (long)(shmaddr), \ +#define __sanitizer_syscall_post_shmat(res, shmid, shmaddr, shmflg) \ + __sanitizer_syscall_post_impl_shmat(res, (long)(shmid), (long)(shmaddr), \ (long)(shmflg)) -#define __sanitizer_syscall_pre_shmget(key, size, flag) \ +#define __sanitizer_syscall_pre_shmget(key, size, flag) \ __sanitizer_syscall_pre_impl_shmget((long)(key), (long)(size), (long)(flag)) -#define __sanitizer_syscall_post_shmget(res, key, size, flag) \ - __sanitizer_syscall_post_impl_shmget(res, (long)(key), (long)(size), \ +#define __sanitizer_syscall_post_shmget(res, key, size, flag) \ + __sanitizer_syscall_post_impl_shmget(res, (long)(key), (long)(size), \ (long)(flag)) -#define __sanitizer_syscall_pre_shmdt(shmaddr) \ +#define __sanitizer_syscall_pre_shmdt(shmaddr) \ __sanitizer_syscall_pre_impl_shmdt((long)(shmaddr)) -#define __sanitizer_syscall_post_shmdt(res, shmaddr) \ +#define __sanitizer_syscall_post_shmdt(res, shmaddr) \ __sanitizer_syscall_post_impl_shmdt(res, (long)(shmaddr)) -#define __sanitizer_syscall_pre_shmctl(shmid, cmd, buf) \ +#define __sanitizer_syscall_pre_shmctl(shmid, cmd, buf) \ __sanitizer_syscall_pre_impl_shmctl((long)(shmid), (long)(cmd), (long)(buf)) -#define __sanitizer_syscall_post_shmctl(res, shmid, cmd, buf) \ - __sanitizer_syscall_post_impl_shmctl(res, (long)(shmid), (long)(cmd), \ +#define __sanitizer_syscall_post_shmctl(res, shmid, cmd, buf) \ + __sanitizer_syscall_post_impl_shmctl(res, (long)(shmid), (long)(cmd), \ (long)(buf)) #define __sanitizer_syscall_pre_ipc(call, first, second, third, ptr, fifth) \ __sanitizer_syscall_pre_impl_ipc((long)(call), (long)(first), \ (long)(second), (long)(third), (long)(ptr), \ (long)(fifth)) -#define __sanitizer_syscall_post_ipc(res, call, first, second, third, ptr, \ - fifth) \ - __sanitizer_syscall_post_impl_ipc(res, (long)(call), (long)(first), \ - (long)(second), (long)(third), \ +#define __sanitizer_syscall_post_ipc(res, call, first, second, third, ptr, \ + fifth) \ + __sanitizer_syscall_post_impl_ipc(res, (long)(call), (long)(first), \ + (long)(second), (long)(third), \ (long)(ptr), (long)(fifth)) -#define __sanitizer_syscall_pre_mq_open(name, oflag, mode, attr) \ - __sanitizer_syscall_pre_impl_mq_open((long)(name), (long)(oflag), \ +#define __sanitizer_syscall_pre_mq_open(name, oflag, mode, attr) \ + __sanitizer_syscall_pre_impl_mq_open((long)(name), (long)(oflag), \ (long)(mode), (long)(attr)) -#define __sanitizer_syscall_post_mq_open(res, name, oflag, mode, attr) \ - __sanitizer_syscall_post_impl_mq_open(res, (long)(name), (long)(oflag), \ +#define __sanitizer_syscall_post_mq_open(res, name, oflag, mode, attr) \ + __sanitizer_syscall_post_impl_mq_open(res, (long)(name), (long)(oflag), \ (long)(mode), (long)(attr)) -#define __sanitizer_syscall_pre_mq_unlink(name) \ +#define __sanitizer_syscall_pre_mq_unlink(name) \ __sanitizer_syscall_pre_impl_mq_unlink((long)(name)) -#define __sanitizer_syscall_post_mq_unlink(res, name) \ +#define __sanitizer_syscall_post_mq_unlink(res, name) \ __sanitizer_syscall_post_impl_mq_unlink(res, (long)(name)) #define __sanitizer_syscall_pre_mq_timedsend(mqdes, msg_ptr, msg_len, \ msg_prio, abs_timeout) \ __sanitizer_syscall_pre_impl_mq_timedsend((long)(mqdes), (long)(msg_ptr), \ (long)(msg_len), (long)(msg_prio), \ (long)(abs_timeout)) -#define __sanitizer_syscall_post_mq_timedsend(res, mqdes, msg_ptr, msg_len, \ - msg_prio, abs_timeout) \ - __sanitizer_syscall_post_impl_mq_timedsend( \ - res, (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \ +#define __sanitizer_syscall_post_mq_timedsend(res, mqdes, msg_ptr, msg_len, \ + msg_prio, abs_timeout) \ + __sanitizer_syscall_post_impl_mq_timedsend( \ + res, (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \ (long)(abs_timeout)) -#define __sanitizer_syscall_pre_mq_timedreceive(mqdes, msg_ptr, msg_len, \ - msg_prio, abs_timeout) \ - __sanitizer_syscall_pre_impl_mq_timedreceive( \ - (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \ +#define __sanitizer_syscall_pre_mq_timedreceive(mqdes, msg_ptr, msg_len, \ + msg_prio, abs_timeout) \ + __sanitizer_syscall_pre_impl_mq_timedreceive( \ + (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \ (long)(abs_timeout)) #define __sanitizer_syscall_post_mq_timedreceive(res, mqdes, msg_ptr, msg_len, \ msg_prio, abs_timeout) \ __sanitizer_syscall_post_impl_mq_timedreceive( \ res, (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \ (long)(abs_timeout)) -#define __sanitizer_syscall_pre_mq_notify(mqdes, notification) \ +#define __sanitizer_syscall_pre_mq_notify(mqdes, notification) \ __sanitizer_syscall_pre_impl_mq_notify((long)(mqdes), (long)(notification)) -#define __sanitizer_syscall_post_mq_notify(res, mqdes, notification) \ - __sanitizer_syscall_post_impl_mq_notify(res, (long)(mqdes), \ +#define __sanitizer_syscall_post_mq_notify(res, mqdes, notification) \ + __sanitizer_syscall_post_impl_mq_notify(res, (long)(mqdes), \ (long)(notification)) -#define __sanitizer_syscall_pre_mq_getsetattr(mqdes, mqstat, omqstat) \ - __sanitizer_syscall_pre_impl_mq_getsetattr((long)(mqdes), (long)(mqstat), \ +#define __sanitizer_syscall_pre_mq_getsetattr(mqdes, mqstat, omqstat) \ + __sanitizer_syscall_pre_impl_mq_getsetattr((long)(mqdes), (long)(mqstat), \ (long)(omqstat)) -#define __sanitizer_syscall_post_mq_getsetattr(res, mqdes, mqstat, omqstat) \ - __sanitizer_syscall_post_impl_mq_getsetattr(res, (long)(mqdes), \ +#define __sanitizer_syscall_post_mq_getsetattr(res, mqdes, mqstat, omqstat) \ + __sanitizer_syscall_post_impl_mq_getsetattr(res, (long)(mqdes), \ (long)(mqstat), (long)(omqstat)) -#define __sanitizer_syscall_pre_pciconfig_iobase(which, bus, devfn) \ - __sanitizer_syscall_pre_impl_pciconfig_iobase((long)(which), (long)(bus), \ +#define __sanitizer_syscall_pre_pciconfig_iobase(which, bus, devfn) \ + __sanitizer_syscall_pre_impl_pciconfig_iobase((long)(which), (long)(bus), \ (long)(devfn)) -#define __sanitizer_syscall_post_pciconfig_iobase(res, which, bus, devfn) \ - __sanitizer_syscall_post_impl_pciconfig_iobase(res, (long)(which), \ +#define __sanitizer_syscall_post_pciconfig_iobase(res, which, bus, devfn) \ + __sanitizer_syscall_post_impl_pciconfig_iobase(res, (long)(which), \ (long)(bus), (long)(devfn)) -#define __sanitizer_syscall_pre_pciconfig_read(bus, dfn, off, len, buf) \ - __sanitizer_syscall_pre_impl_pciconfig_read( \ +#define __sanitizer_syscall_pre_pciconfig_read(bus, dfn, off, len, buf) \ + __sanitizer_syscall_pre_impl_pciconfig_read( \ (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf)) -#define __sanitizer_syscall_post_pciconfig_read(res, bus, dfn, off, len, buf) \ - __sanitizer_syscall_post_impl_pciconfig_read( \ +#define __sanitizer_syscall_post_pciconfig_read(res, bus, dfn, off, len, buf) \ + __sanitizer_syscall_post_impl_pciconfig_read( \ res, (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf)) -#define __sanitizer_syscall_pre_pciconfig_write(bus, dfn, off, len, buf) \ - __sanitizer_syscall_pre_impl_pciconfig_write( \ +#define __sanitizer_syscall_pre_pciconfig_write(bus, dfn, off, len, buf) \ + __sanitizer_syscall_pre_impl_pciconfig_write( \ (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf)) #define __sanitizer_syscall_post_pciconfig_write(res, bus, dfn, off, len, buf) \ __sanitizer_syscall_post_impl_pciconfig_write( \ res, (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf)) -#define __sanitizer_syscall_pre_swapon(specialfile, swap_flags) \ +#define __sanitizer_syscall_pre_swapon(specialfile, swap_flags) \ __sanitizer_syscall_pre_impl_swapon((long)(specialfile), (long)(swap_flags)) -#define __sanitizer_syscall_post_swapon(res, specialfile, swap_flags) \ - __sanitizer_syscall_post_impl_swapon(res, (long)(specialfile), \ +#define __sanitizer_syscall_post_swapon(res, specialfile, swap_flags) \ + __sanitizer_syscall_post_impl_swapon(res, (long)(specialfile), \ (long)(swap_flags)) -#define __sanitizer_syscall_pre_swapoff(specialfile) \ +#define __sanitizer_syscall_pre_swapoff(specialfile) \ __sanitizer_syscall_pre_impl_swapoff((long)(specialfile)) -#define __sanitizer_syscall_post_swapoff(res, specialfile) \ +#define __sanitizer_syscall_post_swapoff(res, specialfile) \ __sanitizer_syscall_post_impl_swapoff(res, (long)(specialfile)) -#define __sanitizer_syscall_pre_sysctl(args) \ +#define __sanitizer_syscall_pre_sysctl(args) \ __sanitizer_syscall_pre_impl_sysctl((long)(args)) -#define __sanitizer_syscall_post_sysctl(res, args) \ +#define __sanitizer_syscall_post_sysctl(res, args) \ __sanitizer_syscall_post_impl_sysctl(res, (long)(args)) -#define __sanitizer_syscall_pre_sysinfo(info) \ +#define __sanitizer_syscall_pre_sysinfo(info) \ __sanitizer_syscall_pre_impl_sysinfo((long)(info)) -#define __sanitizer_syscall_post_sysinfo(res, info) \ +#define __sanitizer_syscall_post_sysinfo(res, info) \ __sanitizer_syscall_post_impl_sysinfo(res, (long)(info)) -#define __sanitizer_syscall_pre_sysfs(option, arg1, arg2) \ +#define __sanitizer_syscall_pre_sysfs(option, arg1, arg2) \ __sanitizer_syscall_pre_impl_sysfs((long)(option), (long)(arg1), (long)(arg2)) -#define __sanitizer_syscall_post_sysfs(res, option, arg1, arg2) \ - __sanitizer_syscall_post_impl_sysfs(res, (long)(option), (long)(arg1), \ +#define __sanitizer_syscall_post_sysfs(res, option, arg1, arg2) \ + __sanitizer_syscall_post_impl_sysfs(res, (long)(option), (long)(arg1), \ (long)(arg2)) -#define __sanitizer_syscall_pre_syslog(type, buf, len) \ +#define __sanitizer_syscall_pre_syslog(type, buf, len) \ __sanitizer_syscall_pre_impl_syslog((long)(type), (long)(buf), (long)(len)) -#define __sanitizer_syscall_post_syslog(res, type, buf, len) \ - __sanitizer_syscall_post_impl_syslog(res, (long)(type), (long)(buf), \ +#define __sanitizer_syscall_post_syslog(res, type, buf, len) \ + __sanitizer_syscall_post_impl_syslog(res, (long)(type), (long)(buf), \ (long)(len)) -#define __sanitizer_syscall_pre_uselib(library) \ +#define __sanitizer_syscall_pre_uselib(library) \ __sanitizer_syscall_pre_impl_uselib((long)(library)) -#define __sanitizer_syscall_post_uselib(res, library) \ +#define __sanitizer_syscall_post_uselib(res, library) \ __sanitizer_syscall_post_impl_uselib(res, (long)(library)) -#define __sanitizer_syscall_pre_ni_syscall() \ +#define __sanitizer_syscall_pre_ni_syscall() \ __sanitizer_syscall_pre_impl_ni_syscall() -#define __sanitizer_syscall_post_ni_syscall(res) \ +#define __sanitizer_syscall_post_ni_syscall(res) \ __sanitizer_syscall_post_impl_ni_syscall(res) -#define __sanitizer_syscall_pre_ptrace(request, pid, addr, data) \ - __sanitizer_syscall_pre_impl_ptrace((long)(request), (long)(pid), \ +#define __sanitizer_syscall_pre_ptrace(request, pid, addr, data) \ + __sanitizer_syscall_pre_impl_ptrace((long)(request), (long)(pid), \ (long)(addr), (long)(data)) -#define __sanitizer_syscall_post_ptrace(res, request, pid, addr, data) \ - __sanitizer_syscall_post_impl_ptrace(res, (long)(request), (long)(pid), \ +#define __sanitizer_syscall_post_ptrace(res, request, pid, addr, data) \ + __sanitizer_syscall_post_impl_ptrace(res, (long)(request), (long)(pid), \ (long)(addr), (long)(data)) -#define __sanitizer_syscall_pre_add_key(_type, _description, _payload, plen, \ - destringid) \ - __sanitizer_syscall_pre_impl_add_key((long)(_type), (long)(_description), \ - (long)(_payload), (long)(plen), \ +#define __sanitizer_syscall_pre_add_key(_type, _description, _payload, plen, \ + destringid) \ + __sanitizer_syscall_pre_impl_add_key((long)(_type), (long)(_description), \ + (long)(_payload), (long)(plen), \ (long)(destringid)) -#define __sanitizer_syscall_post_add_key(res, _type, _description, _payload, \ - plen, destringid) \ - __sanitizer_syscall_post_impl_add_key( \ - res, (long)(_type), (long)(_description), (long)(_payload), \ +#define __sanitizer_syscall_post_add_key(res, _type, _description, _payload, \ + plen, destringid) \ + __sanitizer_syscall_post_impl_add_key( \ + res, (long)(_type), (long)(_description), (long)(_payload), \ (long)(plen), (long)(destringid)) -#define __sanitizer_syscall_pre_request_key(_type, _description, \ - _callout_info, destringid) \ - __sanitizer_syscall_pre_impl_request_key( \ - (long)(_type), (long)(_description), (long)(_callout_info), \ +#define __sanitizer_syscall_pre_request_key(_type, _description, \ + _callout_info, destringid) \ + __sanitizer_syscall_pre_impl_request_key( \ + (long)(_type), (long)(_description), (long)(_callout_info), \ (long)(destringid)) -#define __sanitizer_syscall_post_request_key(res, _type, _description, \ - _callout_info, destringid) \ - __sanitizer_syscall_post_impl_request_key( \ - res, (long)(_type), (long)(_description), (long)(_callout_info), \ +#define __sanitizer_syscall_post_request_key(res, _type, _description, \ + _callout_info, destringid) \ + __sanitizer_syscall_post_impl_request_key( \ + res, (long)(_type), (long)(_description), (long)(_callout_info), \ (long)(destringid)) #define __sanitizer_syscall_pre_keyctl(cmd, arg2, arg3, arg4, arg5) \ __sanitizer_syscall_pre_impl_keyctl((long)(cmd), (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) -#define __sanitizer_syscall_post_keyctl(res, cmd, arg2, arg3, arg4, arg5) \ - __sanitizer_syscall_post_impl_keyctl(res, (long)(cmd), (long)(arg2), \ - (long)(arg3), (long)(arg4), \ +#define __sanitizer_syscall_post_keyctl(res, cmd, arg2, arg3, arg4, arg5) \ + __sanitizer_syscall_post_impl_keyctl(res, (long)(cmd), (long)(arg2), \ + (long)(arg3), (long)(arg4), \ (long)(arg5)) -#define __sanitizer_syscall_pre_ioprio_set(which, who, ioprio) \ - __sanitizer_syscall_pre_impl_ioprio_set((long)(which), (long)(who), \ +#define __sanitizer_syscall_pre_ioprio_set(which, who, ioprio) \ + __sanitizer_syscall_pre_impl_ioprio_set((long)(which), (long)(who), \ (long)(ioprio)) -#define __sanitizer_syscall_post_ioprio_set(res, which, who, ioprio) \ - __sanitizer_syscall_post_impl_ioprio_set(res, (long)(which), (long)(who), \ +#define __sanitizer_syscall_post_ioprio_set(res, which, who, ioprio) \ + __sanitizer_syscall_post_impl_ioprio_set(res, (long)(which), (long)(who), \ (long)(ioprio)) -#define __sanitizer_syscall_pre_ioprio_get(which, who) \ +#define __sanitizer_syscall_pre_ioprio_get(which, who) \ __sanitizer_syscall_pre_impl_ioprio_get((long)(which), (long)(who)) -#define __sanitizer_syscall_post_ioprio_get(res, which, who) \ +#define __sanitizer_syscall_post_ioprio_get(res, which, who) \ __sanitizer_syscall_post_impl_ioprio_get(res, (long)(which), (long)(who)) -#define __sanitizer_syscall_pre_set_mempolicy(mode, nmask, maxnode) \ - __sanitizer_syscall_pre_impl_set_mempolicy((long)(mode), (long)(nmask), \ +#define __sanitizer_syscall_pre_set_mempolicy(mode, nmask, maxnode) \ + __sanitizer_syscall_pre_impl_set_mempolicy((long)(mode), (long)(nmask), \ (long)(maxnode)) -#define __sanitizer_syscall_post_set_mempolicy(res, mode, nmask, maxnode) \ - __sanitizer_syscall_post_impl_set_mempolicy(res, (long)(mode), \ +#define __sanitizer_syscall_post_set_mempolicy(res, mode, nmask, maxnode) \ + __sanitizer_syscall_post_impl_set_mempolicy(res, (long)(mode), \ (long)(nmask), (long)(maxnode)) -#define __sanitizer_syscall_pre_migrate_pages(pid, maxnode, from, to) \ - __sanitizer_syscall_pre_impl_migrate_pages((long)(pid), (long)(maxnode), \ +#define __sanitizer_syscall_pre_migrate_pages(pid, maxnode, from, to) \ + __sanitizer_syscall_pre_impl_migrate_pages((long)(pid), (long)(maxnode), \ (long)(from), (long)(to)) -#define __sanitizer_syscall_post_migrate_pages(res, pid, maxnode, from, to) \ - __sanitizer_syscall_post_impl_migrate_pages( \ +#define __sanitizer_syscall_post_migrate_pages(res, pid, maxnode, from, to) \ + __sanitizer_syscall_post_impl_migrate_pages( \ res, (long)(pid), (long)(maxnode), (long)(from), (long)(to)) -#define __sanitizer_syscall_pre_move_pages(pid, nr_pages, pages, nodes, \ - status, flags) \ - __sanitizer_syscall_pre_impl_move_pages((long)(pid), (long)(nr_pages), \ - (long)(pages), (long)(nodes), \ +#define __sanitizer_syscall_pre_move_pages(pid, nr_pages, pages, nodes, \ + status, flags) \ + __sanitizer_syscall_pre_impl_move_pages((long)(pid), (long)(nr_pages), \ + (long)(pages), (long)(nodes), \ (long)(status), (long)(flags)) #define __sanitizer_syscall_post_move_pages(res, pid, nr_pages, pages, nodes, \ status, flags) \ @@ -1517,322 +1526,320 @@ __sanitizer_syscall_pre_impl_mbind((long)(start), (long)(len), (long)(mode), \ (long)(nmask), (long)(maxnode), \ (long)(flags)) -#define __sanitizer_syscall_post_mbind(res, start, len, mode, nmask, maxnode, \ - flags) \ - __sanitizer_syscall_post_impl_mbind(res, (long)(start), (long)(len), \ - (long)(mode), (long)(nmask), \ +#define __sanitizer_syscall_post_mbind(res, start, len, mode, nmask, maxnode, \ + flags) \ + __sanitizer_syscall_post_impl_mbind(res, (long)(start), (long)(len), \ + (long)(mode), (long)(nmask), \ (long)(maxnode), (long)(flags)) -#define __sanitizer_syscall_pre_get_mempolicy(policy, nmask, maxnode, addr, \ - flags) \ - __sanitizer_syscall_pre_impl_get_mempolicy((long)(policy), (long)(nmask), \ - (long)(maxnode), (long)(addr), \ +#define __sanitizer_syscall_pre_get_mempolicy(policy, nmask, maxnode, addr, \ + flags) \ + __sanitizer_syscall_pre_impl_get_mempolicy((long)(policy), (long)(nmask), \ + (long)(maxnode), (long)(addr), \ (long)(flags)) -#define __sanitizer_syscall_post_get_mempolicy(res, policy, nmask, maxnode, \ - addr, flags) \ - __sanitizer_syscall_post_impl_get_mempolicy(res, (long)(policy), \ - (long)(nmask), (long)(maxnode), \ +#define __sanitizer_syscall_post_get_mempolicy(res, policy, nmask, maxnode, \ + addr, flags) \ + __sanitizer_syscall_post_impl_get_mempolicy(res, (long)(policy), \ + (long)(nmask), (long)(maxnode), \ (long)(addr), (long)(flags)) -#define __sanitizer_syscall_pre_inotify_init() \ +#define __sanitizer_syscall_pre_inotify_init() \ __sanitizer_syscall_pre_impl_inotify_init() -#define __sanitizer_syscall_post_inotify_init(res) \ +#define __sanitizer_syscall_post_inotify_init(res) \ __sanitizer_syscall_post_impl_inotify_init(res) -#define __sanitizer_syscall_pre_inotify_init1(flags) \ +#define __sanitizer_syscall_pre_inotify_init1(flags) \ __sanitizer_syscall_pre_impl_inotify_init1((long)(flags)) -#define __sanitizer_syscall_post_inotify_init1(res, flags) \ +#define __sanitizer_syscall_post_inotify_init1(res, flags) \ __sanitizer_syscall_post_impl_inotify_init1(res, (long)(flags)) -#define __sanitizer_syscall_pre_inotify_add_watch(fd, path, mask) \ - __sanitizer_syscall_pre_impl_inotify_add_watch((long)(fd), (long)(path), \ +#define __sanitizer_syscall_pre_inotify_add_watch(fd, path, mask) \ + __sanitizer_syscall_pre_impl_inotify_add_watch((long)(fd), (long)(path), \ (long)(mask)) -#define __sanitizer_syscall_post_inotify_add_watch(res, fd, path, mask) \ - __sanitizer_syscall_post_impl_inotify_add_watch(res, (long)(fd), \ +#define __sanitizer_syscall_post_inotify_add_watch(res, fd, path, mask) \ + __sanitizer_syscall_post_impl_inotify_add_watch(res, (long)(fd), \ (long)(path), (long)(mask)) -#define __sanitizer_syscall_pre_inotify_rm_watch(fd, wd) \ +#define __sanitizer_syscall_pre_inotify_rm_watch(fd, wd) \ __sanitizer_syscall_pre_impl_inotify_rm_watch((long)(fd), (long)(wd)) -#define __sanitizer_syscall_post_inotify_rm_watch(res, fd, wd) \ +#define __sanitizer_syscall_post_inotify_rm_watch(res, fd, wd) \ __sanitizer_syscall_post_impl_inotify_rm_watch(res, (long)(fd), (long)(wd)) -#define __sanitizer_syscall_pre_spu_run(fd, unpc, ustatus) \ - __sanitizer_syscall_pre_impl_spu_run((long)(fd), (long)(unpc), \ +#define __sanitizer_syscall_pre_spu_run(fd, unpc, ustatus) \ + __sanitizer_syscall_pre_impl_spu_run((long)(fd), (long)(unpc), \ (long)(ustatus)) -#define __sanitizer_syscall_post_spu_run(res, fd, unpc, ustatus) \ - __sanitizer_syscall_post_impl_spu_run(res, (long)(fd), (long)(unpc), \ +#define __sanitizer_syscall_post_spu_run(res, fd, unpc, ustatus) \ + __sanitizer_syscall_post_impl_spu_run(res, (long)(fd), (long)(unpc), \ (long)(ustatus)) -#define __sanitizer_syscall_pre_spu_create(name, flags, mode, fd) \ - __sanitizer_syscall_pre_impl_spu_create((long)(name), (long)(flags), \ +#define __sanitizer_syscall_pre_spu_create(name, flags, mode, fd) \ + __sanitizer_syscall_pre_impl_spu_create((long)(name), (long)(flags), \ (long)(mode), (long)(fd)) -#define __sanitizer_syscall_post_spu_create(res, name, flags, mode, fd) \ - __sanitizer_syscall_post_impl_spu_create(res, (long)(name), (long)(flags), \ +#define __sanitizer_syscall_post_spu_create(res, name, flags, mode, fd) \ + __sanitizer_syscall_post_impl_spu_create(res, (long)(name), (long)(flags), \ (long)(mode), (long)(fd)) -#define __sanitizer_syscall_pre_mknodat(dfd, filename, mode, dev) \ - __sanitizer_syscall_pre_impl_mknodat((long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_pre_mknodat(dfd, filename, mode, dev) \ + __sanitizer_syscall_pre_impl_mknodat((long)(dfd), (long)(filename), \ (long)(mode), (long)(dev)) -#define __sanitizer_syscall_post_mknodat(res, dfd, filename, mode, dev) \ - __sanitizer_syscall_post_impl_mknodat(res, (long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_post_mknodat(res, dfd, filename, mode, dev) \ + __sanitizer_syscall_post_impl_mknodat(res, (long)(dfd), (long)(filename), \ (long)(mode), (long)(dev)) -#define __sanitizer_syscall_pre_mkdirat(dfd, pathname, mode) \ - __sanitizer_syscall_pre_impl_mkdirat((long)(dfd), (long)(pathname), \ +#define __sanitizer_syscall_pre_mkdirat(dfd, pathname, mode) \ + __sanitizer_syscall_pre_impl_mkdirat((long)(dfd), (long)(pathname), \ (long)(mode)) -#define __sanitizer_syscall_post_mkdirat(res, dfd, pathname, mode) \ - __sanitizer_syscall_post_impl_mkdirat(res, (long)(dfd), (long)(pathname), \ +#define __sanitizer_syscall_post_mkdirat(res, dfd, pathname, mode) \ + __sanitizer_syscall_post_impl_mkdirat(res, (long)(dfd), (long)(pathname), \ (long)(mode)) -#define __sanitizer_syscall_pre_unlinkat(dfd, pathname, flag) \ - __sanitizer_syscall_pre_impl_unlinkat((long)(dfd), (long)(pathname), \ +#define __sanitizer_syscall_pre_unlinkat(dfd, pathname, flag) \ + __sanitizer_syscall_pre_impl_unlinkat((long)(dfd), (long)(pathname), \ (long)(flag)) -#define __sanitizer_syscall_post_unlinkat(res, dfd, pathname, flag) \ - __sanitizer_syscall_post_impl_unlinkat(res, (long)(dfd), (long)(pathname), \ +#define __sanitizer_syscall_post_unlinkat(res, dfd, pathname, flag) \ + __sanitizer_syscall_post_impl_unlinkat(res, (long)(dfd), (long)(pathname), \ (long)(flag)) -#define __sanitizer_syscall_pre_symlinkat(oldname, newdfd, newname) \ - __sanitizer_syscall_pre_impl_symlinkat((long)(oldname), (long)(newdfd), \ +#define __sanitizer_syscall_pre_symlinkat(oldname, newdfd, newname) \ + __sanitizer_syscall_pre_impl_symlinkat((long)(oldname), (long)(newdfd), \ (long)(newname)) -#define __sanitizer_syscall_post_symlinkat(res, oldname, newdfd, newname) \ - __sanitizer_syscall_post_impl_symlinkat(res, (long)(oldname), \ +#define __sanitizer_syscall_post_symlinkat(res, oldname, newdfd, newname) \ + __sanitizer_syscall_post_impl_symlinkat(res, (long)(oldname), \ (long)(newdfd), (long)(newname)) -#define __sanitizer_syscall_pre_linkat(olddfd, oldname, newdfd, newname, \ - flags) \ - __sanitizer_syscall_pre_impl_linkat((long)(olddfd), (long)(oldname), \ - (long)(newdfd), (long)(newname), \ +#define __sanitizer_syscall_pre_linkat(olddfd, oldname, newdfd, newname, \ + flags) \ + __sanitizer_syscall_pre_impl_linkat((long)(olddfd), (long)(oldname), \ + (long)(newdfd), (long)(newname), \ (long)(flags)) #define __sanitizer_syscall_post_linkat(res, olddfd, oldname, newdfd, newname, \ flags) \ __sanitizer_syscall_post_impl_linkat(res, (long)(olddfd), (long)(oldname), \ (long)(newdfd), (long)(newname), \ (long)(flags)) -#define __sanitizer_syscall_pre_renameat(olddfd, oldname, newdfd, newname) \ - __sanitizer_syscall_pre_impl_renameat((long)(olddfd), (long)(oldname), \ +#define __sanitizer_syscall_pre_renameat(olddfd, oldname, newdfd, newname) \ + __sanitizer_syscall_pre_impl_renameat((long)(olddfd), (long)(oldname), \ (long)(newdfd), (long)(newname)) #define __sanitizer_syscall_post_renameat(res, olddfd, oldname, newdfd, \ newname) \ __sanitizer_syscall_post_impl_renameat(res, (long)(olddfd), (long)(oldname), \ (long)(newdfd), (long)(newname)) -#define __sanitizer_syscall_pre_futimesat(dfd, filename, utimes) \ - __sanitizer_syscall_pre_impl_futimesat((long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_pre_futimesat(dfd, filename, utimes) \ + __sanitizer_syscall_pre_impl_futimesat((long)(dfd), (long)(filename), \ (long)(utimes)) -#define __sanitizer_syscall_post_futimesat(res, dfd, filename, utimes) \ - __sanitizer_syscall_post_impl_futimesat(res, (long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_post_futimesat(res, dfd, filename, utimes) \ + __sanitizer_syscall_post_impl_futimesat(res, (long)(dfd), (long)(filename), \ (long)(utimes)) -#define __sanitizer_syscall_pre_faccessat(dfd, filename, mode) \ - __sanitizer_syscall_pre_impl_faccessat((long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_pre_faccessat(dfd, filename, mode) \ + __sanitizer_syscall_pre_impl_faccessat((long)(dfd), (long)(filename), \ (long)(mode)) -#define __sanitizer_syscall_post_faccessat(res, dfd, filename, mode) \ - __sanitizer_syscall_post_impl_faccessat(res, (long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_post_faccessat(res, dfd, filename, mode) \ + __sanitizer_syscall_post_impl_faccessat(res, (long)(dfd), (long)(filename), \ (long)(mode)) -#define __sanitizer_syscall_pre_fchmodat(dfd, filename, mode) \ - __sanitizer_syscall_pre_impl_fchmodat((long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_pre_fchmodat(dfd, filename, mode) \ + __sanitizer_syscall_pre_impl_fchmodat((long)(dfd), (long)(filename), \ (long)(mode)) -#define __sanitizer_syscall_post_fchmodat(res, dfd, filename, mode) \ - __sanitizer_syscall_post_impl_fchmodat(res, (long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_post_fchmodat(res, dfd, filename, mode) \ + __sanitizer_syscall_post_impl_fchmodat(res, (long)(dfd), (long)(filename), \ (long)(mode)) -#define __sanitizer_syscall_pre_fchownat(dfd, filename, user, group, flag) \ - __sanitizer_syscall_pre_impl_fchownat((long)(dfd), (long)(filename), \ - (long)(user), (long)(group), \ +#define __sanitizer_syscall_pre_fchownat(dfd, filename, user, group, flag) \ + __sanitizer_syscall_pre_impl_fchownat((long)(dfd), (long)(filename), \ + (long)(user), (long)(group), \ (long)(flag)) -#define __sanitizer_syscall_post_fchownat(res, dfd, filename, user, group, \ - flag) \ - __sanitizer_syscall_post_impl_fchownat(res, (long)(dfd), (long)(filename), \ - (long)(user), (long)(group), \ +#define __sanitizer_syscall_post_fchownat(res, dfd, filename, user, group, \ + flag) \ + __sanitizer_syscall_post_impl_fchownat(res, (long)(dfd), (long)(filename), \ + (long)(user), (long)(group), \ (long)(flag)) -#define __sanitizer_syscall_pre_openat(dfd, filename, flags, mode) \ - __sanitizer_syscall_pre_impl_openat((long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_pre_openat(dfd, filename, flags, mode) \ + __sanitizer_syscall_pre_impl_openat((long)(dfd), (long)(filename), \ (long)(flags), (long)(mode)) -#define __sanitizer_syscall_post_openat(res, dfd, filename, flags, mode) \ - __sanitizer_syscall_post_impl_openat(res, (long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_post_openat(res, dfd, filename, flags, mode) \ + __sanitizer_syscall_post_impl_openat(res, (long)(dfd), (long)(filename), \ (long)(flags), (long)(mode)) -#define __sanitizer_syscall_pre_newfstatat(dfd, filename, statbuf, flag) \ - __sanitizer_syscall_pre_impl_newfstatat((long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_pre_newfstatat(dfd, filename, statbuf, flag) \ + __sanitizer_syscall_pre_impl_newfstatat((long)(dfd), (long)(filename), \ (long)(statbuf), (long)(flag)) #define __sanitizer_syscall_post_newfstatat(res, dfd, filename, statbuf, flag) \ __sanitizer_syscall_post_impl_newfstatat(res, (long)(dfd), (long)(filename), \ (long)(statbuf), (long)(flag)) -#define __sanitizer_syscall_pre_fstatat64(dfd, filename, statbuf, flag) \ - __sanitizer_syscall_pre_impl_fstatat64((long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_pre_fstatat64(dfd, filename, statbuf, flag) \ + __sanitizer_syscall_pre_impl_fstatat64((long)(dfd), (long)(filename), \ (long)(statbuf), (long)(flag)) -#define __sanitizer_syscall_post_fstatat64(res, dfd, filename, statbuf, flag) \ - __sanitizer_syscall_post_impl_fstatat64(res, (long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_post_fstatat64(res, dfd, filename, statbuf, flag) \ + __sanitizer_syscall_post_impl_fstatat64(res, (long)(dfd), (long)(filename), \ (long)(statbuf), (long)(flag)) -#define __sanitizer_syscall_pre_readlinkat(dfd, path, buf, bufsiz) \ - __sanitizer_syscall_pre_impl_readlinkat((long)(dfd), (long)(path), \ +#define __sanitizer_syscall_pre_readlinkat(dfd, path, buf, bufsiz) \ + __sanitizer_syscall_pre_impl_readlinkat((long)(dfd), (long)(path), \ (long)(buf), (long)(bufsiz)) -#define __sanitizer_syscall_post_readlinkat(res, dfd, path, buf, bufsiz) \ - __sanitizer_syscall_post_impl_readlinkat(res, (long)(dfd), (long)(path), \ +#define __sanitizer_syscall_post_readlinkat(res, dfd, path, buf, bufsiz) \ + __sanitizer_syscall_post_impl_readlinkat(res, (long)(dfd), (long)(path), \ (long)(buf), (long)(bufsiz)) -#define __sanitizer_syscall_pre_utimensat(dfd, filename, utimes, flags) \ - __sanitizer_syscall_pre_impl_utimensat((long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_pre_utimensat(dfd, filename, utimes, flags) \ + __sanitizer_syscall_pre_impl_utimensat((long)(dfd), (long)(filename), \ (long)(utimes), (long)(flags)) -#define __sanitizer_syscall_post_utimensat(res, dfd, filename, utimes, flags) \ - __sanitizer_syscall_post_impl_utimensat(res, (long)(dfd), (long)(filename), \ +#define __sanitizer_syscall_post_utimensat(res, dfd, filename, utimes, flags) \ + __sanitizer_syscall_post_impl_utimensat(res, (long)(dfd), (long)(filename), \ (long)(utimes), (long)(flags)) -#define __sanitizer_syscall_pre_unshare(unshare_flags) \ +#define __sanitizer_syscall_pre_unshare(unshare_flags) \ __sanitizer_syscall_pre_impl_unshare((long)(unshare_flags)) -#define __sanitizer_syscall_post_unshare(res, unshare_flags) \ +#define __sanitizer_syscall_post_unshare(res, unshare_flags) \ __sanitizer_syscall_post_impl_unshare(res, (long)(unshare_flags)) -#define __sanitizer_syscall_pre_splice(fd_in, off_in, fd_out, off_out, len, \ - flags) \ - __sanitizer_syscall_pre_impl_splice((long)(fd_in), (long)(off_in), \ - (long)(fd_out), (long)(off_out), \ +#define __sanitizer_syscall_pre_splice(fd_in, off_in, fd_out, off_out, len, \ + flags) \ + __sanitizer_syscall_pre_impl_splice((long)(fd_in), (long)(off_in), \ + (long)(fd_out), (long)(off_out), \ (long)(len), (long)(flags)) -#define __sanitizer_syscall_post_splice(res, fd_in, off_in, fd_out, off_out, \ - len, flags) \ - __sanitizer_syscall_post_impl_splice(res, (long)(fd_in), (long)(off_in), \ - (long)(fd_out), (long)(off_out), \ +#define __sanitizer_syscall_post_splice(res, fd_in, off_in, fd_out, off_out, \ + len, flags) \ + __sanitizer_syscall_post_impl_splice(res, (long)(fd_in), (long)(off_in), \ + (long)(fd_out), (long)(off_out), \ (long)(len), (long)(flags)) -#define __sanitizer_syscall_pre_vmsplice(fd, iov, nr_segs, flags) \ - __sanitizer_syscall_pre_impl_vmsplice((long)(fd), (long)(iov), \ +#define __sanitizer_syscall_pre_vmsplice(fd, iov, nr_segs, flags) \ + __sanitizer_syscall_pre_impl_vmsplice((long)(fd), (long)(iov), \ (long)(nr_segs), (long)(flags)) -#define __sanitizer_syscall_post_vmsplice(res, fd, iov, nr_segs, flags) \ - __sanitizer_syscall_post_impl_vmsplice(res, (long)(fd), (long)(iov), \ +#define __sanitizer_syscall_post_vmsplice(res, fd, iov, nr_segs, flags) \ + __sanitizer_syscall_post_impl_vmsplice(res, (long)(fd), (long)(iov), \ (long)(nr_segs), (long)(flags)) -#define __sanitizer_syscall_pre_tee(fdin, fdout, len, flags) \ - __sanitizer_syscall_pre_impl_tee((long)(fdin), (long)(fdout), (long)(len), \ +#define __sanitizer_syscall_pre_tee(fdin, fdout, len, flags) \ + __sanitizer_syscall_pre_impl_tee((long)(fdin), (long)(fdout), (long)(len), \ (long)(flags)) -#define __sanitizer_syscall_post_tee(res, fdin, fdout, len, flags) \ - __sanitizer_syscall_post_impl_tee(res, (long)(fdin), (long)(fdout), \ +#define __sanitizer_syscall_post_tee(res, fdin, fdout, len, flags) \ + __sanitizer_syscall_post_impl_tee(res, (long)(fdin), (long)(fdout), \ (long)(len), (long)(flags)) -#define __sanitizer_syscall_pre_get_robust_list(pid, head_ptr, len_ptr) \ - __sanitizer_syscall_pre_impl_get_robust_list((long)(pid), (long)(head_ptr), \ +#define __sanitizer_syscall_pre_get_robust_list(pid, head_ptr, len_ptr) \ + __sanitizer_syscall_pre_impl_get_robust_list((long)(pid), (long)(head_ptr), \ (long)(len_ptr)) -#define __sanitizer_syscall_post_get_robust_list(res, pid, head_ptr, len_ptr) \ - __sanitizer_syscall_post_impl_get_robust_list( \ +#define __sanitizer_syscall_post_get_robust_list(res, pid, head_ptr, len_ptr) \ + __sanitizer_syscall_post_impl_get_robust_list( \ res, (long)(pid), (long)(head_ptr), (long)(len_ptr)) -#define __sanitizer_syscall_pre_set_robust_list(head, len) \ +#define __sanitizer_syscall_pre_set_robust_list(head, len) \ __sanitizer_syscall_pre_impl_set_robust_list((long)(head), (long)(len)) -#define __sanitizer_syscall_post_set_robust_list(res, head, len) \ +#define __sanitizer_syscall_post_set_robust_list(res, head, len) \ __sanitizer_syscall_post_impl_set_robust_list(res, (long)(head), (long)(len)) -#define __sanitizer_syscall_pre_getcpu(cpu, node, cache) \ +#define __sanitizer_syscall_pre_getcpu(cpu, node, cache) \ __sanitizer_syscall_pre_impl_getcpu((long)(cpu), (long)(node), (long)(cache)) -#define __sanitizer_syscall_post_getcpu(res, cpu, node, cache) \ - __sanitizer_syscall_post_impl_getcpu(res, (long)(cpu), (long)(node), \ +#define __sanitizer_syscall_post_getcpu(res, cpu, node, cache) \ + __sanitizer_syscall_post_impl_getcpu(res, (long)(cpu), (long)(node), \ (long)(cache)) -#define __sanitizer_syscall_pre_signalfd(ufd, user_mask, sizemask) \ - __sanitizer_syscall_pre_impl_signalfd((long)(ufd), (long)(user_mask), \ +#define __sanitizer_syscall_pre_signalfd(ufd, user_mask, sizemask) \ + __sanitizer_syscall_pre_impl_signalfd((long)(ufd), (long)(user_mask), \ (long)(sizemask)) -#define __sanitizer_syscall_post_signalfd(res, ufd, user_mask, sizemask) \ - __sanitizer_syscall_post_impl_signalfd(res, (long)(ufd), (long)(user_mask), \ +#define __sanitizer_syscall_post_signalfd(res, ufd, user_mask, sizemask) \ + __sanitizer_syscall_post_impl_signalfd(res, (long)(ufd), (long)(user_mask), \ (long)(sizemask)) -#define __sanitizer_syscall_pre_signalfd4(ufd, user_mask, sizemask, flags) \ - __sanitizer_syscall_pre_impl_signalfd4((long)(ufd), (long)(user_mask), \ +#define __sanitizer_syscall_pre_signalfd4(ufd, user_mask, sizemask, flags) \ + __sanitizer_syscall_pre_impl_signalfd4((long)(ufd), (long)(user_mask), \ (long)(sizemask), (long)(flags)) #define __sanitizer_syscall_post_signalfd4(res, ufd, user_mask, sizemask, \ flags) \ __sanitizer_syscall_post_impl_signalfd4(res, (long)(ufd), (long)(user_mask), \ (long)(sizemask), (long)(flags)) -#define __sanitizer_syscall_pre_timerfd_create(clockid, flags) \ +#define __sanitizer_syscall_pre_timerfd_create(clockid, flags) \ __sanitizer_syscall_pre_impl_timerfd_create((long)(clockid), (long)(flags)) -#define __sanitizer_syscall_post_timerfd_create(res, clockid, flags) \ - __sanitizer_syscall_post_impl_timerfd_create(res, (long)(clockid), \ +#define __sanitizer_syscall_post_timerfd_create(res, clockid, flags) \ + __sanitizer_syscall_post_impl_timerfd_create(res, (long)(clockid), \ (long)(flags)) -#define __sanitizer_syscall_pre_timerfd_settime(ufd, flags, utmr, otmr) \ - __sanitizer_syscall_pre_impl_timerfd_settime((long)(ufd), (long)(flags), \ +#define __sanitizer_syscall_pre_timerfd_settime(ufd, flags, utmr, otmr) \ + __sanitizer_syscall_pre_impl_timerfd_settime((long)(ufd), (long)(flags), \ (long)(utmr), (long)(otmr)) -#define __sanitizer_syscall_post_timerfd_settime(res, ufd, flags, utmr, otmr) \ - __sanitizer_syscall_post_impl_timerfd_settime( \ +#define __sanitizer_syscall_post_timerfd_settime(res, ufd, flags, utmr, otmr) \ + __sanitizer_syscall_post_impl_timerfd_settime( \ res, (long)(ufd), (long)(flags), (long)(utmr), (long)(otmr)) -#define __sanitizer_syscall_pre_timerfd_gettime(ufd, otmr) \ +#define __sanitizer_syscall_pre_timerfd_gettime(ufd, otmr) \ __sanitizer_syscall_pre_impl_timerfd_gettime((long)(ufd), (long)(otmr)) -#define __sanitizer_syscall_post_timerfd_gettime(res, ufd, otmr) \ +#define __sanitizer_syscall_post_timerfd_gettime(res, ufd, otmr) \ __sanitizer_syscall_post_impl_timerfd_gettime(res, (long)(ufd), (long)(otmr)) -#define __sanitizer_syscall_pre_eventfd(count) \ +#define __sanitizer_syscall_pre_eventfd(count) \ __sanitizer_syscall_pre_impl_eventfd((long)(count)) -#define __sanitizer_syscall_post_eventfd(res, count) \ +#define __sanitizer_syscall_post_eventfd(res, count) \ __sanitizer_syscall_post_impl_eventfd(res, (long)(count)) -#define __sanitizer_syscall_pre_eventfd2(count, flags) \ +#define __sanitizer_syscall_pre_eventfd2(count, flags) \ __sanitizer_syscall_pre_impl_eventfd2((long)(count), (long)(flags)) -#define __sanitizer_syscall_post_eventfd2(res, count, flags) \ +#define __sanitizer_syscall_post_eventfd2(res, count, flags) \ __sanitizer_syscall_post_impl_eventfd2(res, (long)(count), (long)(flags)) -#define __sanitizer_syscall_pre_old_readdir(arg0, arg1, arg2) \ - __sanitizer_syscall_pre_impl_old_readdir((long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_pre_old_readdir(arg0, arg1, arg2) \ + __sanitizer_syscall_pre_impl_old_readdir((long)(arg0), (long)(arg1), \ (long)(arg2)) -#define __sanitizer_syscall_post_old_readdir(res, arg0, arg1, arg2) \ - __sanitizer_syscall_post_impl_old_readdir(res, (long)(arg0), (long)(arg1), \ +#define __sanitizer_syscall_post_old_readdir(res, arg0, arg1, arg2) \ + __sanitizer_syscall_post_impl_old_readdir(res, (long)(arg0), (long)(arg1), \ (long)(arg2)) -#define __sanitizer_syscall_pre_pselect6(arg0, arg1, arg2, arg3, arg4, arg5) \ - __sanitizer_syscall_pre_impl_pselect6((long)(arg0), (long)(arg1), \ - (long)(arg2), (long)(arg3), \ +#define __sanitizer_syscall_pre_pselect6(arg0, arg1, arg2, arg3, arg4, arg5) \ + __sanitizer_syscall_pre_impl_pselect6((long)(arg0), (long)(arg1), \ + (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) -#define __sanitizer_syscall_post_pselect6(res, arg0, arg1, arg2, arg3, arg4, \ - arg5) \ - __sanitizer_syscall_post_impl_pselect6(res, (long)(arg0), (long)(arg1), \ - (long)(arg2), (long)(arg3), \ +#define __sanitizer_syscall_post_pselect6(res, arg0, arg1, arg2, arg3, arg4, \ + arg5) \ + __sanitizer_syscall_post_impl_pselect6(res, (long)(arg0), (long)(arg1), \ + (long)(arg2), (long)(arg3), \ (long)(arg4), (long)(arg5)) #define __sanitizer_syscall_pre_ppoll(arg0, arg1, arg2, arg3, arg4) \ __sanitizer_syscall_pre_impl_ppoll((long)(arg0), (long)(arg1), (long)(arg2), \ (long)(arg3), (long)(arg4)) -#define __sanitizer_syscall_post_ppoll(res, arg0, arg1, arg2, arg3, arg4) \ - __sanitizer_syscall_post_impl_ppoll(res, (long)(arg0), (long)(arg1), \ - (long)(arg2), (long)(arg3), \ +#define __sanitizer_syscall_post_ppoll(res, arg0, arg1, arg2, arg3, arg4) \ + __sanitizer_syscall_post_impl_ppoll(res, (long)(arg0), (long)(arg1), \ + (long)(arg2), (long)(arg3), \ (long)(arg4)) -#define __sanitizer_syscall_pre_syncfs(fd) \ +#define __sanitizer_syscall_pre_syncfs(fd) \ __sanitizer_syscall_pre_impl_syncfs((long)(fd)) -#define __sanitizer_syscall_post_syncfs(res, fd) \ +#define __sanitizer_syscall_post_syncfs(res, fd) \ __sanitizer_syscall_post_impl_syncfs(res, (long)(fd)) #define __sanitizer_syscall_pre_perf_event_open(attr_uptr, pid, cpu, group_fd, \ flags) \ __sanitizer_syscall_pre_impl_perf_event_open((long)(attr_uptr), (long)(pid), \ (long)(cpu), (long)(group_fd), \ (long)(flags)) -#define __sanitizer_syscall_post_perf_event_open(res, attr_uptr, pid, cpu, \ - group_fd, flags) \ - __sanitizer_syscall_post_impl_perf_event_open( \ - res, (long)(attr_uptr), (long)(pid), (long)(cpu), (long)(group_fd), \ +#define __sanitizer_syscall_post_perf_event_open(res, attr_uptr, pid, cpu, \ + group_fd, flags) \ + __sanitizer_syscall_post_impl_perf_event_open( \ + res, (long)(attr_uptr), (long)(pid), (long)(cpu), (long)(group_fd), \ (long)(flags)) -#define __sanitizer_syscall_pre_mmap_pgoff(addr, len, prot, flags, fd, pgoff) \ - __sanitizer_syscall_pre_impl_mmap_pgoff((long)(addr), (long)(len), \ - (long)(prot), (long)(flags), \ +#define __sanitizer_syscall_pre_mmap_pgoff(addr, len, prot, flags, fd, pgoff) \ + __sanitizer_syscall_pre_impl_mmap_pgoff((long)(addr), (long)(len), \ + (long)(prot), (long)(flags), \ (long)(fd), (long)(pgoff)) -#define __sanitizer_syscall_post_mmap_pgoff(res, addr, len, prot, flags, fd, \ - pgoff) \ - __sanitizer_syscall_post_impl_mmap_pgoff(res, (long)(addr), (long)(len), \ - (long)(prot), (long)(flags), \ +#define __sanitizer_syscall_post_mmap_pgoff(res, addr, len, prot, flags, fd, \ + pgoff) \ + __sanitizer_syscall_post_impl_mmap_pgoff(res, (long)(addr), (long)(len), \ + (long)(prot), (long)(flags), \ (long)(fd), (long)(pgoff)) -#define __sanitizer_syscall_pre_old_mmap(arg) \ +#define __sanitizer_syscall_pre_old_mmap(arg) \ __sanitizer_syscall_pre_impl_old_mmap((long)(arg)) -#define __sanitizer_syscall_post_old_mmap(res, arg) \ +#define __sanitizer_syscall_post_old_mmap(res, arg) \ __sanitizer_syscall_post_impl_old_mmap(res, (long)(arg)) -#define __sanitizer_syscall_pre_name_to_handle_at(dfd, name, handle, mnt_id, \ - flag) \ - __sanitizer_syscall_pre_impl_name_to_handle_at( \ +#define __sanitizer_syscall_pre_name_to_handle_at(dfd, name, handle, mnt_id, \ + flag) \ + __sanitizer_syscall_pre_impl_name_to_handle_at( \ (long)(dfd), (long)(name), (long)(handle), (long)(mnt_id), (long)(flag)) -#define __sanitizer_syscall_post_name_to_handle_at(res, dfd, name, handle, \ - mnt_id, flag) \ - __sanitizer_syscall_post_impl_name_to_handle_at( \ - res, (long)(dfd), (long)(name), (long)(handle), (long)(mnt_id), \ +#define __sanitizer_syscall_post_name_to_handle_at(res, dfd, name, handle, \ + mnt_id, flag) \ + __sanitizer_syscall_post_impl_name_to_handle_at( \ + res, (long)(dfd), (long)(name), (long)(handle), (long)(mnt_id), \ (long)(flag)) -#define __sanitizer_syscall_pre_open_by_handle_at(mountdirfd, handle, flags) \ - __sanitizer_syscall_pre_impl_open_by_handle_at( \ +#define __sanitizer_syscall_pre_open_by_handle_at(mountdirfd, handle, flags) \ + __sanitizer_syscall_pre_impl_open_by_handle_at( \ (long)(mountdirfd), (long)(handle), (long)(flags)) -#define __sanitizer_syscall_post_open_by_handle_at(res, mountdirfd, handle, \ - flags) \ - __sanitizer_syscall_post_impl_open_by_handle_at( \ +#define __sanitizer_syscall_post_open_by_handle_at(res, mountdirfd, handle, \ + flags) \ + __sanitizer_syscall_post_impl_open_by_handle_at( \ res, (long)(mountdirfd), (long)(handle), (long)(flags)) -#define __sanitizer_syscall_pre_setns(fd, nstype) \ +#define __sanitizer_syscall_pre_setns(fd, nstype) \ __sanitizer_syscall_pre_impl_setns((long)(fd), (long)(nstype)) -#define __sanitizer_syscall_post_setns(res, fd, nstype) \ +#define __sanitizer_syscall_post_setns(res, fd, nstype) \ __sanitizer_syscall_post_impl_setns(res, (long)(fd), (long)(nstype)) -#define __sanitizer_syscall_pre_process_vm_readv(pid, lvec, liovcnt, rvec, \ - riovcnt, flags) \ - __sanitizer_syscall_pre_impl_process_vm_readv( \ - (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \ +#define __sanitizer_syscall_pre_process_vm_readv(pid, lvec, liovcnt, rvec, \ + riovcnt, flags) \ + __sanitizer_syscall_pre_impl_process_vm_readv( \ + (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \ (long)(riovcnt), (long)(flags)) -#define __sanitizer_syscall_post_process_vm_readv(res, pid, lvec, liovcnt, \ - rvec, riovcnt, flags) \ - __sanitizer_syscall_post_impl_process_vm_readv( \ - res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \ +#define __sanitizer_syscall_post_process_vm_readv(res, pid, lvec, liovcnt, \ + rvec, riovcnt, flags) \ + __sanitizer_syscall_post_impl_process_vm_readv( \ + res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \ (long)(riovcnt), (long)(flags)) -#define __sanitizer_syscall_pre_process_vm_writev(pid, lvec, liovcnt, rvec, \ - riovcnt, flags) \ - __sanitizer_syscall_pre_impl_process_vm_writev( \ - (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \ +#define __sanitizer_syscall_pre_process_vm_writev(pid, lvec, liovcnt, rvec, \ + riovcnt, flags) \ + __sanitizer_syscall_pre_impl_process_vm_writev( \ + (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \ (long)(riovcnt), (long)(flags)) -#define __sanitizer_syscall_post_process_vm_writev(res, pid, lvec, liovcnt, \ - rvec, riovcnt, flags) \ - __sanitizer_syscall_post_impl_process_vm_writev( \ - res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \ +#define __sanitizer_syscall_post_process_vm_writev(res, pid, lvec, liovcnt, \ + rvec, riovcnt, flags) \ + __sanitizer_syscall_post_impl_process_vm_writev( \ + res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \ (long)(riovcnt), (long)(flags)) -#define __sanitizer_syscall_pre_fork() \ - __sanitizer_syscall_pre_impl_fork() -#define __sanitizer_syscall_post_fork(res) \ +#define __sanitizer_syscall_pre_fork() __sanitizer_syscall_pre_impl_fork() +#define __sanitizer_syscall_post_fork(res) \ __sanitizer_syscall_post_impl_fork(res) -#define __sanitizer_syscall_pre_vfork() \ - __sanitizer_syscall_pre_impl_vfork() -#define __sanitizer_syscall_post_vfork(res) \ +#define __sanitizer_syscall_pre_vfork() __sanitizer_syscall_pre_impl_vfork() +#define __sanitizer_syscall_post_vfork(res) \ __sanitizer_syscall_post_impl_vfork(res) #define __sanitizer_syscall_pre_sigaction(signum, act, oldact) \ __sanitizer_syscall_pre_impl_sigaction((long)signum, (long)act, (long)oldact) @@ -2699,6 +2706,13 @@ void __sanitizer_syscall_pre_impl_epoll_pwait(long epfd, long events, void __sanitizer_syscall_post_impl_epoll_pwait(long res, long epfd, long events, long maxevents, long timeout, long sigmask, long sigsetsize); +void __sanitizer_syscall_pre_impl_epoll_pwait2(long epfd, long events, + long maxevents, long timeout, + long sigmask, long sigsetsize); +void __sanitizer_syscall_post_impl_epoll_pwait2(long res, long epfd, + long events, long maxevents, + long timeout, long sigmask, + long sigsetsize); void __sanitizer_syscall_pre_impl_gethostname(long name, long len); void __sanitizer_syscall_post_impl_gethostname(long res, long name, long len); void __sanitizer_syscall_pre_impl_sethostname(long name, long len); @@ -3080,7 +3094,7 @@ void __sanitizer_syscall_post_impl_rt_sigaction(long res, long signum, long act, void __sanitizer_syscall_pre_impl_sigaltstack(long ss, long oss); void __sanitizer_syscall_post_impl_sigaltstack(long res, long ss, long oss); #ifdef __cplusplus -} // extern "C" +} // extern "C" #endif -#endif // SANITIZER_LINUX_SYSCALL_HOOKS_H +#endif // SANITIZER_LINUX_SYSCALL_HOOKS_H diff --git a/gnu/llvm/compiler-rt/include/sanitizer/msan_interface.h b/gnu/llvm/compiler-rt/include/sanitizer/msan_interface.h index eeb39fbed8b..854b12cda36 100644 --- a/gnu/llvm/compiler-rt/include/sanitizer/msan_interface.h +++ b/gnu/llvm/compiler-rt/include/sanitizer/msan_interface.h @@ -92,6 +92,8 @@ extern "C" { /* Tell MSan about newly destroyed memory. Mark memory as uninitialized. */ void __sanitizer_dtor_callback(const volatile void* data, size_t size); + void __sanitizer_dtor_callback_fields(const volatile void *data, size_t size); + void __sanitizer_dtor_callback_vptr(const volatile void *data); /* This function may be optionally provided by user and should return a string containing Msan runtime options. See msan_flags.h for details. */ diff --git a/gnu/llvm/compiler-rt/include/sanitizer/tsan_interface.h b/gnu/llvm/compiler-rt/include/sanitizer/tsan_interface.h index 565aa391a9f..2782e61fb8c 100644 --- a/gnu/llvm/compiler-rt/include/sanitizer/tsan_interface.h +++ b/gnu/llvm/compiler-rt/include/sanitizer/tsan_interface.h @@ -169,6 +169,9 @@ void __tsan_on_initialize(); // if TSan should exit as if issues were detected. int __tsan_on_finalize(int failed); +// Release TSan internal memory in a best-effort manner. +void __tsan_flush_memory(); + #ifdef __cplusplus } // extern "C" #endif diff --git a/gnu/llvm/compiler-rt/lib/CMakeLists.txt b/gnu/llvm/compiler-rt/lib/CMakeLists.txt index 1437e37b86d..a9a5b1c1009 100644 --- a/gnu/llvm/compiler-rt/lib/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/lib/CMakeLists.txt @@ -17,19 +17,20 @@ if(COMPILER_RT_BUILD_BUILTINS) add_subdirectory(builtins) endif() -if(COMPILER_RT_BUILD_CRT AND COMPILER_RT_HAS_CRT) +if(COMPILER_RT_BUILD_CRT) add_subdirectory(crt) endif() function(compiler_rt_build_runtime runtime) string(TOUPPER ${runtime} runtime_uppercase) if(COMPILER_RT_HAS_${runtime_uppercase}) - add_subdirectory(${runtime}) if(${runtime} STREQUAL tsan) add_subdirectory(tsan/dd) endif() - if(${runtime} STREQUAL scudo) + if(${runtime} STREQUAL scudo_standalone) add_subdirectory(scudo/standalone) + else() + add_subdirectory(${runtime}) endif() endif() endfunction() diff --git a/gnu/llvm/compiler-rt/lib/asan/CMakeLists.txt b/gnu/llvm/compiler-rt/lib/asan/CMakeLists.txt index df009a5a6a2..08fd68ab7ac 100644 --- a/gnu/llvm/compiler-rt/lib/asan/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/lib/asan/CMakeLists.txt @@ -42,6 +42,16 @@ set(ASAN_CXX_SOURCES asan_new_delete.cpp ) +set(ASAN_STATIC_SOURCES + asan_rtl_static.cpp + ) + +if (NOT WIN32 AND NOT APPLE) + list(APPEND ASAN_STATIC_SOURCES + asan_rtl_x86_64.S + ) +endif() + set(ASAN_PREINIT_SOURCES asan_preinit.cpp ) @@ -80,6 +90,14 @@ set(ASAN_COMMON_DEFINITIONS ${COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION}) append_rtti_flag(OFF ASAN_CFLAGS) +# Silence warnings in system headers with MSVC. +if(NOT CLANG_CL) + append_list_if(COMPILER_RT_HAS_EXTERNAL_FLAG "/experimental:external /external:W0 /external:anglebrackets" ASAN_CFLAGS) +endif() + +# Too many existing bugs, needs cleanup. +append_list_if(COMPILER_RT_HAS_WNO_FORMAT -Wno-format ASAN_CFLAGS) + set(ASAN_DYNAMIC_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS}) if(ANDROID) @@ -99,7 +117,10 @@ append_list_if(COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC -ftls-model=initial-exec ASAN_DYNAMIC_CFLAGS) append_list_if(MSVC /DEBUG ASAN_DYNAMIC_LINK_FLAGS) -set(ASAN_DYNAMIC_LIBS ${SANITIZER_CXX_ABI_LIBRARIES} ${SANITIZER_COMMON_LINK_LIBS}) +set(ASAN_DYNAMIC_LIBS + ${COMPILER_RT_UNWINDER_LINK_LIBS} + ${SANITIZER_CXX_ABI_LIBRARIES} + ${SANITIZER_COMMON_LINK_LIBS}) append_list_if(COMPILER_RT_HAS_LIBDL dl ASAN_DYNAMIC_LIBS) append_list_if(COMPILER_RT_HAS_LIBRT rt ASAN_DYNAMIC_LIBS) @@ -131,6 +152,12 @@ if(NOT APPLE) ADDITIONAL_HEADERS ${ASAN_HEADERS} CFLAGS ${ASAN_CFLAGS} DEFS ${ASAN_COMMON_DEFINITIONS}) + add_compiler_rt_object_libraries(RTAsan_static + ARCHS ${ASAN_SUPPORTED_ARCH} + SOURCES ${ASAN_STATIC_SOURCES} + ADDITIONAL_HEADERS ${ASAN_HEADERS} + CFLAGS ${ASAN_CFLAGS} + DEFS ${ASAN_COMMON_DEFINITIONS}) add_compiler_rt_object_libraries(RTAsan_preinit ARCHS ${ASAN_SUPPORTED_ARCH} SOURCES ${ASAN_PREINIT_SOURCES} @@ -172,6 +199,14 @@ if(APPLE) LINK_FLAGS ${WEAK_SYMBOL_LINK_FLAGS} DEFS ${ASAN_DYNAMIC_DEFINITIONS} PARENT_TARGET asan) + + add_compiler_rt_runtime(clang_rt.asan_static + STATIC + ARCHS ${ASAN_SUPPORTED_ARCH} + OBJECT_LIBS RTAsan_static + CFLAGS ${ASAN_CFLAGS} + DEFS ${ASAN_COMMON_DEFINITIONS} + PARENT_TARGET asan) else() # Build separate libraries for each target. @@ -203,6 +238,14 @@ else() DEFS ${ASAN_COMMON_DEFINITIONS} PARENT_TARGET asan) + add_compiler_rt_runtime(clang_rt.asan_static + STATIC + ARCHS ${ASAN_SUPPORTED_ARCH} + OBJECT_LIBS RTAsan_static + CFLAGS ${ASAN_CFLAGS} + DEFS ${ASAN_COMMON_DEFINITIONS} + PARENT_TARGET asan) + add_compiler_rt_runtime(clang_rt.asan-preinit STATIC ARCHS ${ASAN_SUPPORTED_ARCH} @@ -236,7 +279,8 @@ else() add_compiler_rt_object_libraries(AsanWeakInterception ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${arch} - SOURCES asan_win_weak_interception.cpp + SOURCES + asan_win_weak_interception.cpp CFLAGS ${ASAN_CFLAGS} -DSANITIZER_DYNAMIC DEFS ${ASAN_COMMON_DEFINITIONS}) set(ASAN_DYNAMIC_WEAK_INTERCEPTION diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_activation.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_activation.cpp index 795df95a541..1757838600c 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_activation.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_activation.cpp @@ -112,7 +112,7 @@ void AsanDeactivate() { disabled.quarantine_size_mb = 0; disabled.thread_local_quarantine_size_kb = 0; // Redzone must be at least Max(16, granularity) bytes long. - disabled.min_redzone = Max(16, (int)SHADOW_GRANULARITY); + disabled.min_redzone = Max(16, (int)ASAN_SHADOW_GRANULARITY); disabled.max_redzone = disabled.min_redzone; disabled.alloc_dealloc_mismatch = false; disabled.may_return_null = true; diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_allocator.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_allocator.cpp index 414fba3b427..74183fcd242 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_allocator.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_allocator.cpp @@ -102,19 +102,18 @@ class ChunkHeader { public: uptr UsedSize() const { - uptr R = user_requested_size_lo; - if (sizeof(uptr) > sizeof(user_requested_size_lo)) - R += (uptr)user_requested_size_hi << (8 * sizeof(user_requested_size_lo)); - return R; + static_assert(sizeof(user_requested_size_lo) == 4, + "Expression below requires this"); + return FIRST_32_SECOND_64(0, ((uptr)user_requested_size_hi << 32)) + + user_requested_size_lo; } void SetUsedSize(uptr size) { user_requested_size_lo = size; - if (sizeof(uptr) > sizeof(user_requested_size_lo)) { - size >>= (8 * sizeof(user_requested_size_lo)); - user_requested_size_hi = size; - CHECK_EQ(user_requested_size_hi, size); - } + static_assert(sizeof(user_requested_size_lo) == 4, + "Expression below requires this"); + user_requested_size_hi = FIRST_32_SECOND_64(0, size >> 32); + CHECK_EQ(UsedSize(), size); } void SetAllocContext(u32 tid, u32 stack) { @@ -211,8 +210,7 @@ struct QuarantineCallback { CHECK_EQ(old_chunk_state, CHUNK_QUARANTINE); } - PoisonShadow(m->Beg(), - RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY), + PoisonShadow(m->Beg(), RoundUpTo(m->UsedSize(), ASAN_SHADOW_GRANULARITY), kAsanHeapLeftRedzoneMagic); // Statistics. @@ -306,7 +304,6 @@ struct Allocator { QuarantineCache fallback_quarantine_cache; uptr max_user_defined_malloc_size; - atomic_uint8_t rss_limit_exceeded; // ------------------- Options -------------------------- atomic_uint16_t min_redzone; @@ -346,14 +343,6 @@ struct Allocator { : kMaxAllowedMallocSize; } - bool RssLimitExceeded() { - return atomic_load(&rss_limit_exceeded, memory_order_relaxed); - } - - void SetRssLimitExceeded(bool limit_exceeded) { - atomic_store(&rss_limit_exceeded, limit_exceeded, memory_order_relaxed); - } - void RePoisonChunk(uptr chunk) { // This could be a user-facing chunk (with redzones), or some internal // housekeeping chunk, like TransferBatch. Start by assuming the former. @@ -367,7 +356,7 @@ struct Allocator { if (chunk < beg && beg < end && end <= chunk_end) { // Looks like a valid AsanChunk in use, poison redzones only. PoisonShadow(chunk, beg - chunk, kAsanHeapLeftRedzoneMagic); - uptr end_aligned_down = RoundDownTo(end, SHADOW_GRANULARITY); + uptr end_aligned_down = RoundDownTo(end, ASAN_SHADOW_GRANULARITY); FastPoisonShadowPartialRightRedzone( end_aligned_down, end - end_aligned_down, chunk_end - end_aligned_down, kAsanHeapLeftRedzoneMagic); @@ -485,14 +474,14 @@ struct Allocator { AllocType alloc_type, bool can_fill) { if (UNLIKELY(!asan_inited)) AsanInitFromRtl(); - if (RssLimitExceeded()) { + if (UNLIKELY(IsRssLimitExceeded())) { if (AllocatorMayReturnNull()) return nullptr; ReportRssLimitExceeded(stack); } Flags &fl = *flags(); CHECK(stack); - const uptr min_alignment = SHADOW_GRANULARITY; + const uptr min_alignment = ASAN_SHADOW_GRANULARITY; const uptr user_requested_alignment_log = ComputeUserRequestedAlignmentLog(alignment); if (alignment < min_alignment) @@ -522,7 +511,7 @@ struct Allocator { size > max_user_defined_malloc_size) { if (AllocatorMayReturnNull()) { Report("WARNING: AddressSanitizer failed to allocate 0x%zx bytes\n", - (void*)size); + size); return nullptr; } uptr malloc_limit = @@ -573,7 +562,7 @@ struct Allocator { m->SetAllocContext(t ? t->tid() : kMainTid, StackDepotPut(*stack)); uptr size_rounded_down_to_granularity = - RoundDownTo(size, SHADOW_GRANULARITY); + RoundDownTo(size, ASAN_SHADOW_GRANULARITY); // Unpoison the bulk of the memory region. if (size_rounded_down_to_granularity) PoisonShadow(user_beg, size_rounded_down_to_granularity, 0); @@ -581,7 +570,7 @@ struct Allocator { if (size != size_rounded_down_to_granularity && CanPoisonMemory()) { u8 *shadow = (u8 *)MemToShadow(user_beg + size_rounded_down_to_granularity); - *shadow = fl.poison_partial ? (size & (SHADOW_GRANULARITY - 1)) : 0; + *shadow = fl.poison_partial ? (size & (ASAN_SHADOW_GRANULARITY - 1)) : 0; } AsanStats &thread_stats = GetCurrentThreadStats(); @@ -608,7 +597,7 @@ struct Allocator { CHECK_LE(alloc_beg + sizeof(LargeChunkHeader), chunk_beg); reinterpret_cast(alloc_beg)->Set(m); } - ASAN_MALLOC_HOOK(res, size); + RunMallocHooks(res, size); return res; } @@ -651,8 +640,7 @@ struct Allocator { } // Poison the region. - PoisonShadow(m->Beg(), - RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY), + PoisonShadow(m->Beg(), RoundUpTo(m->UsedSize(), ASAN_SHADOW_GRANULARITY), kAsanHeapFreeMagic); AsanStats &thread_stats = GetCurrentThreadStats(); @@ -690,7 +678,7 @@ struct Allocator { return; } - ASAN_FREE_HOOK(ptr); + RunFreeHooks(ptr); // Must mark the chunk as quarantined before any changes to its metadata. // Do not quarantine given chunk if we failed to set CHUNK_QUARANTINE flag. @@ -815,8 +803,8 @@ struct Allocator { sptr offset = 0; if (!m1 || AsanChunkView(m1).AddrIsAtLeft(addr, 1, &offset)) { // The address is in the chunk's left redzone, so maybe it is actually - // a right buffer overflow from the other chunk to the left. - // Search a bit to the left to see if there is another chunk. + // a right buffer overflow from the other chunk before. + // Search a bit before to see if there is another chunk. AsanChunk *m2 = nullptr; for (uptr l = 1; l < GetPageSizeCached(); l++) { m2 = GetAsanChunkByAddr(addr - l); @@ -852,12 +840,12 @@ struct Allocator { quarantine.PrintStats(); } - void ForceLock() ACQUIRE(fallback_mutex) { + void ForceLock() SANITIZER_ACQUIRE(fallback_mutex) { allocator.ForceLock(); fallback_mutex.Lock(); } - void ForceUnlock() RELEASE(fallback_mutex) { + void ForceUnlock() SANITIZER_RELEASE(fallback_mutex) { fallback_mutex.Unlock(); allocator.ForceUnlock(); } @@ -908,13 +896,6 @@ AllocType AsanChunkView::GetAllocType() const { return (AllocType)chunk_->alloc_type; } -static StackTrace GetStackTraceFromId(u32 id) { - CHECK(id); - StackTrace res = StackDepotGet(id); - CHECK(res.trace); - return res; -} - u32 AsanChunkView::GetAllocStackId() const { u32 tid = 0; u32 stack = 0; @@ -931,14 +912,6 @@ u32 AsanChunkView::GetFreeStackId() const { return stack; } -StackTrace AsanChunkView::GetAllocStack() const { - return GetStackTraceFromId(GetAllocStackId()); -} - -StackTrace AsanChunkView::GetFreeStack() const { - return GetStackTraceFromId(GetFreeStackId()); -} - void InitializeAllocator(const AllocatorOptions &options) { instance.InitLinkerInitialized(options); } @@ -1081,14 +1054,12 @@ uptr asan_mz_size(const void *ptr) { return instance.AllocationSize(reinterpret_cast(ptr)); } -void asan_mz_force_lock() NO_THREAD_SAFETY_ANALYSIS { instance.ForceLock(); } - -void asan_mz_force_unlock() NO_THREAD_SAFETY_ANALYSIS { - instance.ForceUnlock(); +void asan_mz_force_lock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS { + instance.ForceLock(); } -void AsanSoftRssLimitExceededCallback(bool limit_exceeded) { - instance.SetRssLimitExceeded(limit_exceeded); +void asan_mz_force_unlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS { + instance.ForceUnlock(); } } // namespace __asan @@ -1123,6 +1094,8 @@ uptr PointsIntoChunk(void *p) { } uptr GetUserBegin(uptr chunk) { + // FIXME: All usecases provide chunk address, GetAsanChunkByAddrFastLocked is + // not needed. __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddrFastLocked(chunk); return m ? m->Beg() : 0; } @@ -1182,33 +1155,6 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) { return kIgnoreObjectSuccess; } -void GetAdditionalThreadContextPtrs(ThreadContextBase *tctx, void *ptrs) { - // Look for the arg pointer of threads that have been created or are running. - // This is necessary to prevent false positive leaks due to the AsanThread - // holding the only live reference to a heap object. This can happen because - // the `pthread_create()` interceptor doesn't wait for the child thread to - // start before returning and thus loosing the the only live reference to the - // heap object on the stack. - - __asan::AsanThreadContext *atctx = - reinterpret_cast<__asan::AsanThreadContext *>(tctx); - __asan::AsanThread *asan_thread = atctx->thread; - - // Note ThreadStatusRunning is required because there is a small window where - // the thread status switches to `ThreadStatusRunning` but the `arg` pointer - // still isn't on the stack yet. - if (atctx->status != ThreadStatusCreated && - atctx->status != ThreadStatusRunning) - return; - - uptr thread_arg = reinterpret_cast(asan_thread->get_arg()); - if (!thread_arg) - return; - - auto ptrsVec = reinterpret_cast *>(ptrs); - ptrsVec->push_back(thread_arg); -} - } // namespace __lsan // ---------------------- Interface ---------------- {{{1 @@ -1246,16 +1192,3 @@ int __asan_update_allocation_context(void* addr) { GET_STACK_TRACE_MALLOC; return instance.UpdateAllocationStack((uptr)addr, &stack); } - -#if !SANITIZER_SUPPORTS_WEAK_HOOKS -// Provide default (no-op) implementation of malloc hooks. -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_malloc_hook, - void *ptr, uptr size) { - (void)ptr; - (void)size; -} - -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_free_hook, void *ptr) { - (void)ptr; -} -#endif diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_allocator.h b/gnu/llvm/compiler-rt/lib/asan/asan_allocator.h index 2963e979b55..0b4dbf03bb9 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_allocator.h +++ b/gnu/llvm/compiler-rt/lib/asan/asan_allocator.h @@ -64,8 +64,6 @@ class AsanChunkView { bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; } u32 GetAllocStackId() const; u32 GetFreeStackId() const; - StackTrace GetAllocStack() const; - StackTrace GetFreeStack() const; AllocType GetAllocType() const; bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) const { if (addr >= Beg() && (addr + access_size) <= End()) { @@ -137,12 +135,6 @@ typedef VeryCompactSizeClassMap SizeClassMap; const uptr kAllocatorSpace = ~(uptr)0; const uptr kAllocatorSize = 0x2000000000ULL; // 128G. typedef VeryDenseSizeClassMap SizeClassMap; -# elif defined(__aarch64__) -// AArch64/SANITIZER_CAN_USE_ALLOCATOR64 is only for 42-bit VMA -// so no need to different values for different VMA. -const uptr kAllocatorSpace = 0x10000000000ULL; -const uptr kAllocatorSize = 0x10000000000ULL; // 3T. -typedef DefaultSizeClassMap SizeClassMap; #elif defined(__sparc__) const uptr kAllocatorSpace = ~(uptr)0; const uptr kAllocatorSize = 0x20000000000ULL; // 2T. diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_debugging.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_debugging.cpp index c01360b52fc..f078f1041a8 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_debugging.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_debugging.cpp @@ -19,6 +19,7 @@ #include "asan_mapping.h" #include "asan_report.h" #include "asan_thread.h" +#include "sanitizer_common/sanitizer_stackdepot.h" namespace { using namespace __asan; @@ -54,11 +55,11 @@ uptr AsanGetStack(uptr addr, uptr *trace, u32 size, u32 *thread_id, StackTrace stack(nullptr, 0); if (alloc_stack) { if (chunk.AllocTid() == kInvalidTid) return 0; - stack = chunk.GetAllocStack(); + stack = StackDepotGet(chunk.GetAllocStackId()); if (thread_id) *thread_id = chunk.AllocTid(); } else { if (chunk.FreeTid() == kInvalidTid) return 0; - stack = chunk.GetFreeStack(); + stack = StackDepotGet(chunk.GetFreeStackId()); if (thread_id) *thread_id = chunk.FreeTid(); } @@ -140,7 +141,7 @@ uptr __asan_get_free_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id) { SANITIZER_INTERFACE_ATTRIBUTE void __asan_get_shadow_mapping(uptr *shadow_scale, uptr *shadow_offset) { if (shadow_scale) - *shadow_scale = SHADOW_SCALE; + *shadow_scale = ASAN_SHADOW_SCALE; if (shadow_offset) - *shadow_offset = SHADOW_OFFSET; + *shadow_offset = ASAN_SHADOW_OFFSET; } diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_descriptions.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_descriptions.cpp index 2ba8a02f841..fbe92572b55 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_descriptions.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_descriptions.cpp @@ -129,11 +129,11 @@ static void PrintHeapChunkAccess(uptr addr, const ChunkAccess &descr) { str.append("%s", d.Location()); switch (descr.access_type) { case kAccessTypeLeft: - str.append("%p is located %zd bytes to the left of", + str.append("%p is located %zd bytes before", (void *)descr.bad_addr, descr.offset); break; case kAccessTypeRight: - str.append("%p is located %zd bytes to the right of", + str.append("%p is located %zd bytes after", (void *)descr.bad_addr, descr.offset); break; case kAccessTypeInside: @@ -251,7 +251,7 @@ static void PrintAccessAndVarIntersection(const StackVarDescr &var, uptr addr, } str.append("'"); if (var.line > 0) { - str.append(" (line %d)", var.line); + str.append(" (line %zd)", var.line); } if (pos_descr) { Decorator d; @@ -279,17 +279,17 @@ static void DescribeAddressRelativeToGlobal(uptr addr, uptr access_size, Decorator d; str.append("%s", d.Location()); if (addr < g.beg) { - str.append("%p is located %zd bytes to the left", (void *)addr, + str.append("%p is located %zd bytes before", (void *)addr, g.beg - addr); } else if (addr + access_size > g.beg + g.size) { if (addr < g.beg + g.size) addr = g.beg + g.size; - str.append("%p is located %zd bytes to the right", (void *)addr, + str.append("%p is located %zd bytes after", (void *)addr, addr - (g.beg + g.size)); } else { // Can it happen? - str.append("%p is located %zd bytes inside", (void *)addr, addr - g.beg); + str.append("%p is located %zd bytes inside of", (void *)addr, addr - g.beg); } - str.append(" of global variable '%s' defined in '", + str.append(" global variable '%s' defined in '", MaybeDemangleGlobalName(g.name)); PrintGlobalLocation(&str, g); str.append("' (0x%zx) of size %zu\n", g.beg, g.size); @@ -318,7 +318,8 @@ bool DescribeAddressIfGlobal(uptr addr, uptr access_size, } void ShadowAddressDescription::Print() const { - Printf("Address %p is located in the %s area.\n", addr, ShadowNames[kind]); + Printf("Address %p is located in the %s area.\n", (void *)addr, + ShadowNames[kind]); } void GlobalAddressDescription::Print(const char *bug_type) const { @@ -356,7 +357,7 @@ bool GlobalAddressDescription::PointsInsideTheSameVariable( void StackAddressDescription::Print() const { Decorator d; Printf("%s", d.Location()); - Printf("Address %p is located in stack of thread %s", addr, + Printf("Address %p is located in stack of thread %s", (void *)addr, AsanThreadIdAndName(tid).c_str()); if (!frame_descr) { @@ -469,7 +470,7 @@ AddressDescription::AddressDescription(uptr addr, uptr access_size, void WildAddressDescription::Print() const { Printf("Address %p is a wild pointer inside of access range of size %p.\n", - addr, access_size); + (void *)addr, (void *)access_size); } void PrintAddressDescription(uptr addr, uptr access_size, diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_errors.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_errors.cpp index 45166c06487..cc8dc26f5b7 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_errors.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_errors.cpp @@ -46,10 +46,9 @@ void ErrorDeadlySignal::Print() { void ErrorDoubleFree::Print() { Decorator d; Printf("%s", d.Error()); - Report( - "ERROR: AddressSanitizer: attempting %s on %p in thread %s:\n", - scariness.GetDescription(), addr_description.addr, - AsanThreadIdAndName(tid).c_str()); + Report("ERROR: AddressSanitizer: attempting %s on %p in thread %s:\n", + scariness.GetDescription(), (void *)addr_description.addr, + AsanThreadIdAndName(tid).c_str()); Printf("%s", d.Default()); scariness.Print(); GET_STACK_TRACE_FATAL(second_free_stack->trace[0], @@ -62,10 +61,9 @@ void ErrorDoubleFree::Print() { void ErrorNewDeleteTypeMismatch::Print() { Decorator d; Printf("%s", d.Error()); - Report( - "ERROR: AddressSanitizer: %s on %p in thread %s:\n", - scariness.GetDescription(), addr_description.addr, - AsanThreadIdAndName(tid).c_str()); + Report("ERROR: AddressSanitizer: %s on %p in thread %s:\n", + scariness.GetDescription(), (void *)addr_description.addr, + AsanThreadIdAndName(tid).c_str()); Printf("%s object passed to delete has wrong type:\n", d.Default()); if (delete_size != 0) { Printf( @@ -106,7 +104,7 @@ void ErrorFreeNotMalloced::Print() { Report( "ERROR: AddressSanitizer: attempting free on address " "which was not malloc()-ed: %p in thread %s\n", - addr_description.Address(), AsanThreadIdAndName(tid).c_str()); + (void *)addr_description.Address(), AsanThreadIdAndName(tid).c_str()); Printf("%s", d.Default()); CHECK_GT(free_stack->size, 0); scariness.Print(); @@ -126,7 +124,7 @@ void ErrorAllocTypeMismatch::Print() { Printf("%s", d.Error()); Report("ERROR: AddressSanitizer: %s (%s vs %s) on %p\n", scariness.GetDescription(), alloc_names[alloc_type], - dealloc_names[dealloc_type], addr_description.Address()); + dealloc_names[dealloc_type], (void *)addr_description.Address()); Printf("%s", d.Default()); CHECK_GT(dealloc_stack->size, 0); scariness.Print(); @@ -145,7 +143,7 @@ void ErrorMallocUsableSizeNotOwned::Print() { Report( "ERROR: AddressSanitizer: attempting to call malloc_usable_size() for " "pointer which is not owned: %p\n", - addr_description.Address()); + (void *)addr_description.Address()); Printf("%s", d.Default()); stack->Print(); addr_description.Print(); @@ -158,7 +156,7 @@ void ErrorSanitizerGetAllocatedSizeNotOwned::Print() { Report( "ERROR: AddressSanitizer: attempting to call " "__sanitizer_get_allocated_size() for pointer which is not owned: %p\n", - addr_description.Address()); + (void *)addr_description.Address()); Printf("%s", d.Default()); stack->Print(); addr_description.Print(); @@ -281,9 +279,7 @@ void ErrorRssLimitExceeded::Print() { void ErrorOutOfMemory::Print() { Decorator d; Printf("%s", d.Error()); - Report( - "ERROR: AddressSanitizer: allocator is out of memory trying to allocate " - "0x%zx bytes\n", requested_size); + ERROR_OOM("allocator is trying to allocate 0x%zx bytes\n", requested_size); Printf("%s", d.Default()); stack->Print(); PrintHintAllocatorCannotReturnNull(); @@ -298,9 +294,10 @@ void ErrorStringFunctionMemoryRangesOverlap::Print() { Report( "ERROR: AddressSanitizer: %s: memory ranges [%p,%p) and [%p, %p) " "overlap\n", - bug_type, addr1_description.Address(), - addr1_description.Address() + length1, addr2_description.Address(), - addr2_description.Address() + length2); + bug_type, (void *)addr1_description.Address(), + (void *)(addr1_description.Address() + length1), + (void *)addr2_description.Address(), + (void *)(addr2_description.Address() + length2)); Printf("%s", d.Default()); scariness.Print(); stack->Print(); @@ -329,10 +326,30 @@ void ErrorBadParamsToAnnotateContiguousContainer::Print() { " end : %p\n" " old_mid : %p\n" " new_mid : %p\n", - beg, end, old_mid, new_mid); - uptr granularity = SHADOW_GRANULARITY; + (void *)beg, (void *)end, (void *)old_mid, (void *)new_mid); + uptr granularity = ASAN_SHADOW_GRANULARITY; if (!IsAligned(beg, granularity)) - Report("ERROR: beg is not aligned by %d\n", granularity); + Report("ERROR: beg is not aligned by %zu\n", granularity); + stack->Print(); + ReportErrorSummary(scariness.GetDescription(), stack); +} + +void ErrorBadParamsToAnnotateDoubleEndedContiguousContainer::Print() { + Report( + "ERROR: AddressSanitizer: bad parameters to " + "__sanitizer_annotate_double_ended_contiguous_container:\n" + " storage_beg : %p\n" + " storage_end : %p\n" + " old_container_beg : %p\n" + " old_container_end : %p\n" + " new_container_beg : %p\n" + " new_container_end : %p\n", + (void *)storage_beg, (void *)storage_end, (void *)old_container_beg, + (void *)old_container_end, (void *)new_container_beg, + (void *)new_container_end); + uptr granularity = ASAN_SHADOW_GRANULARITY; + if (!IsAligned(storage_beg, granularity)) + Report("ERROR: storage_beg is not aligned by %zu\n", granularity); stack->Print(); ReportErrorSummary(scariness.GetDescription(), stack); } @@ -341,7 +358,7 @@ void ErrorODRViolation::Print() { Decorator d; Printf("%s", d.Error()); Report("ERROR: AddressSanitizer: %s (%p):\n", scariness.GetDescription(), - global1.beg); + (void *)global1.beg); Printf("%s", d.Default()); InternalScopedString g1_loc; InternalScopedString g2_loc; @@ -371,7 +388,8 @@ void ErrorInvalidPointerPair::Print() { Decorator d; Printf("%s", d.Error()); Report("ERROR: AddressSanitizer: %s: %p %p\n", scariness.GetDescription(), - addr1_description.Address(), addr2_description.Address()); + (void *)addr1_description.Address(), + (void *)addr2_description.Address()); Printf("%s", d.Default()); GET_STACK_TRACE_FATAL(pc, bp); stack.Print(); @@ -410,7 +428,8 @@ ErrorGeneric::ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr, if (AddrIsInMem(addr)) { u8 *shadow_addr = (u8 *)MemToShadow(addr); // If we are accessing 16 bytes, look at the second shadow byte. - if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY) shadow_addr++; + if (*shadow_addr == 0 && access_size > ASAN_SHADOW_GRANULARITY) + shadow_addr++; // If we are in the partial right redzone, look at the next shadow byte. if (*shadow_addr > 0 && *shadow_addr < 128) shadow_addr++; bool far_from_bounds = false; @@ -501,10 +520,11 @@ static void PrintLegend(InternalScopedString *str) { str->append( "Shadow byte legend (one shadow byte represents %d " "application bytes):\n", - (int)SHADOW_GRANULARITY); + (int)ASAN_SHADOW_GRANULARITY); PrintShadowByte(str, " Addressable: ", 0); str->append(" Partially addressable: "); - for (u8 i = 1; i < SHADOW_GRANULARITY; i++) PrintShadowByte(str, "", i, " "); + for (u8 i = 1; i < ASAN_SHADOW_GRANULARITY; i++) + PrintShadowByte(str, "", i, " "); str->append("\n"); PrintShadowByte(str, " Heap left redzone: ", kAsanHeapLeftRedzoneMagic); @@ -538,7 +558,9 @@ static void PrintLegend(InternalScopedString *str) { static void PrintShadowBytes(InternalScopedString *str, const char *before, u8 *bytes, u8 *guilty, uptr n) { Decorator d; - if (before) str->append("%s%p:", before, bytes); + if (before) + str->append("%s%p:", before, + (void *)ShadowToMem(reinterpret_cast(bytes))); for (uptr i = 0; i < n; i++) { u8 *p = bytes + i; const char *before = @@ -575,7 +597,7 @@ void ErrorGeneric::Print() { Printf("%s", d.Error()); uptr addr = addr_description.Address(); Report("ERROR: AddressSanitizer: %s on address %p at pc %p bp %p sp %p\n", - bug_descr, (void *)addr, pc, bp, sp); + bug_descr, (void *)addr, (void *)pc, (void *)bp, (void *)sp); Printf("%s", d.Default()); Printf("%s%s of size %zu at %p thread %s%s\n", d.Access(), diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_errors.h b/gnu/llvm/compiler-rt/lib/asan/asan_errors.h index a7fda2fd9f5..634f6da5443 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_errors.h +++ b/gnu/llvm/compiler-rt/lib/asan/asan_errors.h @@ -53,9 +53,9 @@ struct ErrorDeadlySignal : ErrorBase { scariness.Scare(10, "null-deref"); } else if (signal.addr == signal.pc) { scariness.Scare(60, "wild-jump"); - } else if (signal.write_flag == SignalContext::WRITE) { + } else if (signal.write_flag == SignalContext::Write) { scariness.Scare(30, "wild-addr-write"); - } else if (signal.write_flag == SignalContext::READ) { + } else if (signal.write_flag == SignalContext::Read) { scariness.Scare(20, "wild-addr-read"); } else { scariness.Scare(25, "wild-addr"); @@ -331,6 +331,28 @@ struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase { void Print(); }; +struct ErrorBadParamsToAnnotateDoubleEndedContiguousContainer : ErrorBase { + const BufferedStackTrace *stack; + uptr storage_beg, storage_end, old_container_beg, old_container_end, + new_container_beg, new_container_end; + + ErrorBadParamsToAnnotateDoubleEndedContiguousContainer() = default; // (*) + ErrorBadParamsToAnnotateDoubleEndedContiguousContainer( + u32 tid, BufferedStackTrace *stack_, uptr storage_beg_, uptr storage_end_, + uptr old_container_beg_, uptr old_container_end_, uptr new_container_beg_, + uptr new_container_end_) + : ErrorBase(tid, 10, + "bad-__sanitizer_annotate_double_ended_contiguous_container"), + stack(stack_), + storage_beg(storage_beg_), + storage_end(storage_end_), + old_container_beg(old_container_beg_), + old_container_end(old_container_end_), + new_container_beg(new_container_beg_), + new_container_end(new_container_end_) {} + void Print(); +}; + struct ErrorODRViolation : ErrorBase { __asan_global global1, global2; u32 stack_id1, stack_id2; @@ -372,34 +394,35 @@ struct ErrorGeneric : ErrorBase { u8 shadow_val; ErrorGeneric() = default; // (*) - ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_, + ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr, bool is_write_, uptr access_size_); void Print(); }; // clang-format off -#define ASAN_FOR_EACH_ERROR_KIND(macro) \ - macro(DeadlySignal) \ - macro(DoubleFree) \ - macro(NewDeleteTypeMismatch) \ - macro(FreeNotMalloced) \ - macro(AllocTypeMismatch) \ - macro(MallocUsableSizeNotOwned) \ - macro(SanitizerGetAllocatedSizeNotOwned) \ - macro(CallocOverflow) \ - macro(ReallocArrayOverflow) \ - macro(PvallocOverflow) \ - macro(InvalidAllocationAlignment) \ - macro(InvalidAlignedAllocAlignment) \ - macro(InvalidPosixMemalignAlignment) \ - macro(AllocationSizeTooBig) \ - macro(RssLimitExceeded) \ - macro(OutOfMemory) \ - macro(StringFunctionMemoryRangesOverlap) \ - macro(StringFunctionSizeOverflow) \ - macro(BadParamsToAnnotateContiguousContainer) \ - macro(ODRViolation) \ - macro(InvalidPointerPair) \ +#define ASAN_FOR_EACH_ERROR_KIND(macro) \ + macro(DeadlySignal) \ + macro(DoubleFree) \ + macro(NewDeleteTypeMismatch) \ + macro(FreeNotMalloced) \ + macro(AllocTypeMismatch) \ + macro(MallocUsableSizeNotOwned) \ + macro(SanitizerGetAllocatedSizeNotOwned) \ + macro(CallocOverflow) \ + macro(ReallocArrayOverflow) \ + macro(PvallocOverflow) \ + macro(InvalidAllocationAlignment) \ + macro(InvalidAlignedAllocAlignment) \ + macro(InvalidPosixMemalignAlignment) \ + macro(AllocationSizeTooBig) \ + macro(RssLimitExceeded) \ + macro(OutOfMemory) \ + macro(StringFunctionMemoryRangesOverlap) \ + macro(StringFunctionSizeOverflow) \ + macro(BadParamsToAnnotateContiguousContainer) \ + macro(BadParamsToAnnotateDoubleEndedContiguousContainer) \ + macro(ODRViolation) \ + macro(InvalidPointerPair) \ macro(Generic) // clang-format on diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_fake_stack.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_fake_stack.cpp index bf5c342ee59..74a039b6579 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_fake_stack.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_fake_stack.cpp @@ -28,8 +28,8 @@ static const u64 kAllocaRedzoneMask = 31UL; // For small size classes inline PoisonShadow for better performance. ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) { u64 *shadow = reinterpret_cast(MemToShadow(ptr)); - if (SHADOW_SCALE == 3 && class_id <= 6) { - // This code expects SHADOW_SCALE=3. + if (ASAN_SHADOW_SCALE == 3 && class_id <= 6) { + // This code expects ASAN_SHADOW_SCALE=3. for (uptr i = 0; i < (((uptr)1) << class_id); i++) { shadow[i] = magic; // Make sure this does not become memset. @@ -54,10 +54,11 @@ FakeStack *FakeStack::Create(uptr stack_size_log) { : MmapOrDie(size, "FakeStack")); res->stack_size_log_ = stack_size_log; u8 *p = reinterpret_cast(res); - VReport(1, "T%d: FakeStack created: %p -- %p stack_size_log: %zd; " + VReport(1, + "T%d: FakeStack created: %p -- %p stack_size_log: %zd; " "mmapped %zdK, noreserve=%d \n", - GetCurrentTidOrInvalid(), p, - p + FakeStack::RequiredSize(stack_size_log), stack_size_log, + GetCurrentTidOrInvalid(), (void *)p, + (void *)(p + FakeStack::RequiredSize(stack_size_log)), stack_size_log, size >> 10, flags()->uar_noreserve); return res; } @@ -139,7 +140,6 @@ void FakeStack::HandleNoReturn() { // We do it based on their 'real_stack' values -- everything that is lower // than the current real_stack is garbage. NOINLINE void FakeStack::GC(uptr real_stack) { - uptr collected = 0; for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++) { u8 *flags = GetFlags(stack_size_log(), class_id); for (uptr i = 0, n = NumberOfFrames(stack_size_log(), class_id); i < n; @@ -149,7 +149,6 @@ NOINLINE void FakeStack::GC(uptr real_stack) { GetFrame(stack_size_log(), class_id, i)); if (ff->real_stack < real_stack) { flags[i] = 0; - collected++; } } } @@ -293,10 +292,10 @@ void __asan_alloca_poison(uptr addr, uptr size) { uptr LeftRedzoneAddr = addr - kAllocaRedzoneSize; uptr PartialRzAddr = addr + size; uptr RightRzAddr = (PartialRzAddr + kAllocaRedzoneMask) & ~kAllocaRedzoneMask; - uptr PartialRzAligned = PartialRzAddr & ~(SHADOW_GRANULARITY - 1); + uptr PartialRzAligned = PartialRzAddr & ~(ASAN_SHADOW_GRANULARITY - 1); FastPoisonShadow(LeftRedzoneAddr, kAllocaRedzoneSize, kAsanAllocaLeftMagic); FastPoisonShadowPartialRightRedzone( - PartialRzAligned, PartialRzAddr % SHADOW_GRANULARITY, + PartialRzAligned, PartialRzAddr % ASAN_SHADOW_GRANULARITY, RightRzAddr - PartialRzAligned, kAsanAllocaRightMagic); FastPoisonShadow(RightRzAddr, kAllocaRedzoneSize, kAsanAllocaRightMagic); } @@ -304,7 +303,8 @@ void __asan_alloca_poison(uptr addr, uptr size) { SANITIZER_INTERFACE_ATTRIBUTE void __asan_allocas_unpoison(uptr top, uptr bottom) { if ((!top) || (top > bottom)) return; - REAL(memset)(reinterpret_cast(MemToShadow(top)), 0, - (bottom - top) / SHADOW_GRANULARITY); + REAL(memset) + (reinterpret_cast(MemToShadow(top)), 0, + (bottom - top) / ASAN_SHADOW_GRANULARITY); } } // extern "C" diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_flags.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_flags.cpp index c64e4647028..23989843323 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_flags.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_flags.cpp @@ -87,7 +87,7 @@ void InitializeFlags() { RegisterCommonFlags(&ubsan_parser); #endif - if (SANITIZER_MAC) { + if (SANITIZER_APPLE) { // Support macOS MallocScribble and MallocPreScribble: // @@ -140,9 +140,9 @@ void InitializeFlags() { SanitizerToolName); Die(); } - // Ensure that redzone is at least SHADOW_GRANULARITY. - if (f->redzone < (int)SHADOW_GRANULARITY) - f->redzone = SHADOW_GRANULARITY; + // Ensure that redzone is at least ASAN_SHADOW_GRANULARITY. + if (f->redzone < (int)ASAN_SHADOW_GRANULARITY) + f->redzone = ASAN_SHADOW_GRANULARITY; // Make "strict_init_order" imply "check_initialization_order". // TODO(samsonov): Use a single runtime flag for an init-order checker. if (f->strict_init_order) { diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_flags.inc b/gnu/llvm/compiler-rt/lib/asan/asan_flags.inc index 514b225c407..fad1577d912 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_flags.inc +++ b/gnu/llvm/compiler-rt/lib/asan/asan_flags.inc @@ -49,9 +49,10 @@ ASAN_FLAG( "to find more errors.") ASAN_FLAG(bool, replace_intrin, true, "If set, uses custom wrappers for memset/memcpy/memmove intrinsics.") -ASAN_FLAG(bool, detect_stack_use_after_return, false, +ASAN_FLAG(bool, detect_stack_use_after_return, + SANITIZER_LINUX && !SANITIZER_ANDROID, "Enables stack-use-after-return checking at run-time.") -ASAN_FLAG(int, min_uar_stack_size_log, 16, // We can't do smaller anyway. +ASAN_FLAG(int, min_uar_stack_size_log, 16, // We can't do smaller anyway. "Minimum fake stack size log.") ASAN_FLAG(int, max_uar_stack_size_log, 20, // 1Mb per size class, i.e. ~11Mb per thread @@ -82,6 +83,10 @@ ASAN_FLAG( int, sleep_after_init, 0, "Number of seconds to sleep after AddressSanitizer is initialized. " "Useful for debugging purposes (e.g. when one needs to attach gdb).") +ASAN_FLAG( + int, sleep_before_init, 0, + "Number of seconds to sleep before AddressSanitizer starts initializing. " + "Useful for debugging purposes (e.g. when one needs to attach gdb).") ASAN_FLAG(bool, check_malloc_usable_size, true, "Allows the users to work around the bug in Nvidia drivers prior to " "295.*.") @@ -117,7 +122,7 @@ ASAN_FLAG(bool, poison_array_cookie, true, // 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 && !SANITIZER_WINDOWS && !SANITIZER_ANDROID, + !SANITIZER_APPLE && !SANITIZER_WINDOWS && !SANITIZER_ANDROID, "Report errors on malloc/delete, new/free, new/delete[], etc.") ASAN_FLAG(bool, new_delete_type_mismatch, true, diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_fuchsia.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_fuchsia.cpp index b0c7255144a..2b15504123b 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_fuchsia.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_fuchsia.cpp @@ -14,16 +14,17 @@ #include "sanitizer_common/sanitizer_fuchsia.h" #if SANITIZER_FUCHSIA -#include "asan_interceptors.h" -#include "asan_internal.h" -#include "asan_stack.h" -#include "asan_thread.h" - #include #include #include #include +# include "asan_interceptors.h" +# include "asan_internal.h" +# include "asan_stack.h" +# include "asan_thread.h" +# include "lsan/lsan_common.h" + namespace __asan { // The system already set up the shadow memory for us. @@ -31,7 +32,8 @@ namespace __asan { // AsanInitInternal->InitializeHighMemEnd (asan_rtl.cpp). // Just do some additional sanity checks here. void InitializeShadowMemory() { - if (Verbosity()) PrintAddressSpaceLayout(); + if (Verbosity()) + PrintAddressSpaceLayout(); // Make sure SHADOW_OFFSET doesn't use __asan_shadow_memory_dynamic_address. __asan_shadow_memory_dynamic_address = kDefaultShadowSentinel; @@ -62,7 +64,34 @@ void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { UNIMPLEMENTED(); } -bool PlatformUnpoisonStacks() { return false; } +bool PlatformUnpoisonStacks() { + // The current sp might not point to the default stack. This + // could be because we are in a crash stack from fuzzing for example. + // Unpoison the default stack and the current stack page. + AsanThread *curr_thread = GetCurrentThread(); + CHECK(curr_thread != nullptr); + uptr top = curr_thread->stack_top(); + uptr bottom = curr_thread->stack_bottom(); + // The default stack grows from top to bottom. (bottom < top). + + uptr local_stack = reinterpret_cast(__builtin_frame_address(0)); + if (local_stack >= bottom && local_stack <= top) { + // The current stack is the default stack. + // We only need to unpoison from where we are using until the end. + bottom = RoundDownTo(local_stack, GetPageSize()); + UnpoisonStack(bottom, top, "default"); + } else { + // The current stack is not the default stack. + // Unpoison the entire default stack and the current stack page. + UnpoisonStack(bottom, top, "default"); + bottom = RoundDownTo(local_stack, GetPageSize()); + top = bottom + GetPageSize(); + UnpoisonStack(bottom, top, "unknown"); + return true; + } + + return false; +} // We can use a plain thread_local variable for TSD. static thread_local void *per_thread; @@ -90,14 +119,12 @@ struct AsanThread::InitOptions { // Shared setup between thread creation and startup for the initial thread. static AsanThread *CreateAsanThread(StackTrace *stack, u32 parent_tid, - uptr user_id, bool detached, - const char *name) { + bool detached, const char *name) { // In lieu of AsanThread::Create. AsanThread *thread = (AsanThread *)MmapOrDie(AsanThreadMmapSize(), __func__); AsanThreadContext::CreateThreadContextArgs args = {thread, stack}; - u32 tid = - asanThreadRegistry().CreateThread(user_id, detached, parent_tid, &args); + u32 tid = asanThreadRegistry().CreateThread(0, detached, parent_tid, &args); asanThreadRegistry().SetThreadName(tid, name); return thread; @@ -124,7 +151,7 @@ AsanThread *CreateMainThread() { CHECK_NE(__sanitizer::MainThreadStackBase, 0); CHECK_GT(__sanitizer::MainThreadStackSize, 0); AsanThread *t = CreateAsanThread( - nullptr, 0, reinterpret_cast(self), true, + nullptr, 0, true, _zx_object_get_property(thrd_get_zx_handle(self), ZX_PROP_NAME, name, sizeof(name)) == ZX_OK ? name @@ -148,13 +175,13 @@ static void *BeforeThreadCreateHook(uptr user_id, bool detached, uptr stack_size) { EnsureMainThreadIDIsCorrect(); // Strict init-order checking is thread-hostile. - if (flags()->strict_init_order) StopInitOrderChecking(); + if (flags()->strict_init_order) + StopInitOrderChecking(); GET_STACK_TRACE_THREAD; u32 parent_tid = GetCurrentTidOrInvalid(); - AsanThread *thread = - CreateAsanThread(&stack, parent_tid, user_id, detached, name); + AsanThread *thread = CreateAsanThread(&stack, parent_tid, detached, name); // On other systems, AsanThread::Init() is called from the new // thread itself. But on Fuchsia we already know the stack address @@ -209,8 +236,18 @@ void FlushUnneededASanShadowMemory(uptr p, uptr size) { __sanitizer_fill_shadow(p, size, 0, 0); } +// On Fuchsia, leak detection is done by a special hook after atexit hooks. +// So this doesn't install any atexit hook like on other platforms. +void InstallAtExitCheckLeaks() {} + } // namespace __asan +namespace __lsan { + +bool UseExitcodeOnLeak() { return __asan::flags()->halt_on_error; } + +} // namespace __lsan + // These are declared (in extern "C") by . // The system runtime will call our definitions directly. diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_globals.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_globals.cpp index 9d7dbc6f264..b780128c9ad 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_globals.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_globals.cpp @@ -35,7 +35,7 @@ struct ListOfGlobals { ListOfGlobals *next; }; -static BlockingMutex mu_for_globals(LINKER_INITIALIZED); +static Mutex mu_for_globals; static LowLevelAllocator allocator_for_globals; static ListOfGlobals *list_of_all_globals; @@ -61,14 +61,13 @@ ALWAYS_INLINE void PoisonShadowForGlobal(const Global *g, u8 value) { } ALWAYS_INLINE void PoisonRedZones(const Global &g) { - uptr aligned_size = RoundUpTo(g.size, SHADOW_GRANULARITY); + uptr aligned_size = RoundUpTo(g.size, ASAN_SHADOW_GRANULARITY); FastPoisonShadow(g.beg + aligned_size, g.size_with_redzone - aligned_size, kAsanGlobalRedzoneMagic); if (g.size != aligned_size) { FastPoisonShadowPartialRightRedzone( - g.beg + RoundDownTo(g.size, SHADOW_GRANULARITY), - g.size % SHADOW_GRANULARITY, - SHADOW_GRANULARITY, + g.beg + RoundDownTo(g.size, ASAN_SHADOW_GRANULARITY), + g.size % ASAN_SHADOW_GRANULARITY, ASAN_SHADOW_GRANULARITY, kAsanGlobalRedzoneMagic); } } @@ -85,12 +84,13 @@ static void ReportGlobal(const Global &g, const char *prefix) { Report( "%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu " "odr_indicator=%p\n", - prefix, &g, (void *)g.beg, g.size, g.size_with_redzone, g.name, + prefix, (void *)&g, (void *)g.beg, g.size, g.size_with_redzone, g.name, g.module_name, g.has_dynamic_init, (void *)g.odr_indicator); - if (g.location) { - Report(" location (%p): name=%s[%p], %d %d\n", g.location, - g.location->filename, g.location->filename, g.location->line_no, - g.location->column_no); + + DataInfo info; + Symbolizer::GetOrInit()->SymbolizeData(g.beg, &info); + if (info.line != 0) { + Report(" location: name=%s, %d\n", info.file, static_cast(info.line)); } } @@ -108,7 +108,7 @@ static u32 FindRegistrationSite(const Global *g) { int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites, int max_globals) { if (!flags()->report_globals) return 0; - BlockingMutexLock lock(&mu_for_globals); + Lock lock(&mu_for_globals); int res = 0; for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { const Global &g = *l->g; @@ -257,7 +257,7 @@ static void UnregisterGlobal(const Global *g) { } void StopInitOrderChecking() { - BlockingMutexLock lock(&mu_for_globals); + Lock lock(&mu_for_globals); if (!flags()->check_initialization_order || !dynamic_init_globals) return; flags()->check_initialization_order = false; @@ -296,19 +296,15 @@ void PrintGlobalNameIfASCII(InternalScopedString *str, const __asan_global &g) { (char *)g.beg); } -static const char *GlobalFilename(const __asan_global &g) { - const char *res = g.module_name; - // Prefer the filename from source location, if is available. - if (g.location) res = g.location->filename; - CHECK(res); - return res; -} - void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g) { - str->append("%s", GlobalFilename(g)); - if (!g.location) return; - if (g.location->line_no) str->append(":%d", g.location->line_no); - if (g.location->column_no) str->append(":%d", g.location->column_no); + DataInfo info; + Symbolizer::GetOrInit()->SymbolizeData(g.beg, &info); + + if (info.line != 0) { + str->append("%s:%d", info.file, static_cast(info.line)); + } else { + str->append("%s", g.module_name); + } } } // namespace __asan @@ -359,7 +355,7 @@ void __asan_register_globals(__asan_global *globals, uptr n) { if (!flags()->report_globals) return; GET_STACK_TRACE_MALLOC; u32 stack_id = StackDepotPut(stack); - BlockingMutexLock lock(&mu_for_globals); + Lock lock(&mu_for_globals); if (!global_registration_site_vector) { global_registration_site_vector = new (allocator_for_globals) GlobalRegistrationSiteVector; @@ -369,7 +365,8 @@ void __asan_register_globals(__asan_global *globals, uptr n) { global_registration_site_vector->push_back(site); if (flags()->report_globals >= 2) { PRINT_CURRENT_STACK(); - Printf("=== ID %d; %p %p\n", stack_id, &globals[0], &globals[n - 1]); + Printf("=== ID %d; %p %p\n", stack_id, (void *)&globals[0], + (void *)&globals[n - 1]); } for (uptr i = 0; i < n; i++) { if (SANITIZER_WINDOWS && globals[i].beg == 0) { @@ -398,7 +395,7 @@ void __asan_register_globals(__asan_global *globals, uptr n) { // We must do this when a shared objects gets dlclosed. void __asan_unregister_globals(__asan_global *globals, uptr n) { if (!flags()->report_globals) return; - BlockingMutexLock lock(&mu_for_globals); + Lock lock(&mu_for_globals); for (uptr i = 0; i < n; i++) { if (SANITIZER_WINDOWS && globals[i].beg == 0) { // Skip globals that look like padding from the MSVC incremental linker. @@ -424,7 +421,7 @@ void __asan_before_dynamic_init(const char *module_name) { bool strict_init_order = flags()->strict_init_order; CHECK(module_name); CHECK(asan_inited); - BlockingMutexLock lock(&mu_for_globals); + Lock lock(&mu_for_globals); if (flags()->report_globals >= 3) Printf("DynInitPoison module: %s\n", module_name); for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { @@ -448,7 +445,7 @@ void __asan_after_dynamic_init() { !dynamic_init_globals) return; CHECK(asan_inited); - BlockingMutexLock lock(&mu_for_globals); + Lock lock(&mu_for_globals); // FIXME: Optionally report that we're unpoisoning globals from a module. for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) { DynInitGlobal &dyn_g = (*dynamic_init_globals)[i]; diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_interceptors.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_interceptors.cpp index d0a6dd48a74..776f512d08a 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_interceptors.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_interceptors.cpp @@ -49,8 +49,8 @@ namespace __asan { ASAN_READ_RANGE((ctx), (s), \ common_flags()->strict_string_checks ? (len) + 1 : (n)) -#define ASAN_READ_STRING(ctx, s, n) \ - ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n)) +# define ASAN_READ_STRING(ctx, s, n) \ + ASAN_READ_STRING_OF_LEN((ctx), (s), internal_strlen(s), (n)) static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { #if SANITIZER_INTERCEPT_STRNLEN @@ -103,7 +103,7 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) do { \ if (asan_init_is_running) \ return REAL(func)(__VA_ARGS__); \ - if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \ + if (SANITIZER_APPLE && UNLIKELY(!asan_inited)) \ return REAL(func)(__VA_ARGS__); \ ENSURE_ASAN_INITED(); \ } while (false) @@ -130,23 +130,24 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) // Strict init-order checking is dlopen-hostile: // https://github.com/google/sanitizers/issues/178 -#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \ - do { \ - if (flags()->strict_init_order) \ - StopInitOrderChecking(); \ - CheckNoDeepBind(filename, flag); \ - } while (false) -#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() -#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) -#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() -#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited) -#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ - if (AsanThread *t = GetCurrentThread()) { \ - *begin = t->tls_begin(); \ - *end = t->tls_end(); \ - } else { \ - *begin = *end = 0; \ - } +# define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \ + ({ \ + if (flags()->strict_init_order) \ + StopInitOrderChecking(); \ + CheckNoDeepBind(filename, flag); \ + REAL(dlopen)(filename, flag); \ + }) +# define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() +# define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) +# define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() +# define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited) +# define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ + if (AsanThread *t = GetCurrentThread()) { \ + *begin = t->tls_begin(); \ + *end = t->tls_end(); \ + } else { \ + *begin = *end = 0; \ + } #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \ do { \ @@ -242,15 +243,50 @@ DEFINE_REAL_PTHREAD_FUNCTIONS #if ASAN_INTERCEPT_SWAPCONTEXT static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { + // Only clear if we know the stack. This should be true only for contexts + // created with makecontext(). + if (!ssize) + return; // Align to page size. uptr PageSize = GetPageSizeCached(); - uptr bottom = stack & ~(PageSize - 1); + uptr bottom = RoundDownTo(stack, PageSize); + if (!AddrIsInMem(bottom)) + return; ssize += stack - bottom; ssize = RoundUpTo(ssize, PageSize); - static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb - if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) { - PoisonShadow(bottom, ssize, 0); - } + PoisonShadow(bottom, ssize, 0); +} + +INTERCEPTOR(void, makecontext, struct ucontext_t *ucp, void (*func)(), int argc, + ...) { + va_list ap; + uptr args[64]; + // We don't know a better way to forward ... into REAL function. We can + // increase args size if neccecary. + CHECK_LE(argc, ARRAY_SIZE(args)); + internal_memset(args, 0, sizeof(args)); + va_start(ap, argc); + for (int i = 0; i < argc; ++i) args[i] = va_arg(ap, uptr); + va_end(ap); + +# define ENUMERATE_ARRAY_4(start) \ + args[start], args[start + 1], args[start + 2], args[start + 3] +# define ENUMERATE_ARRAY_16(start) \ + ENUMERATE_ARRAY_4(start), ENUMERATE_ARRAY_4(start + 4), \ + ENUMERATE_ARRAY_4(start + 8), ENUMERATE_ARRAY_4(start + 12) +# define ENUMERATE_ARRAY_64() \ + ENUMERATE_ARRAY_16(0), ENUMERATE_ARRAY_16(16), ENUMERATE_ARRAY_16(32), \ + ENUMERATE_ARRAY_16(48) + + REAL(makecontext) + ((struct ucontext_t *)ucp, func, argc, ENUMERATE_ARRAY_64()); + +# undef ENUMERATE_ARRAY_4 +# undef ENUMERATE_ARRAY_16 +# undef ENUMERATE_ARRAY_64 + + // Sign the stack so we can identify it for unpoisoning. + SignContextStack(ucp); } INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, @@ -266,15 +302,15 @@ INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, uptr stack, ssize; ReadContextStack(ucp, &stack, &ssize); ClearShadowMemoryForContextStack(stack, ssize); -#if __has_attribute(__indirect_return__) && \ - (defined(__x86_64__) || defined(__i386__)) + +# if __has_attribute(__indirect_return__) && \ + (defined(__x86_64__) || defined(__i386__)) int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *) - __attribute__((__indirect_return__)) - = REAL(swapcontext); + __attribute__((__indirect_return__)) = REAL(swapcontext); int res = real_swapcontext(oucp, ucp); -#else +# else int res = REAL(swapcontext)(oucp, ucp); -#endif +# endif // swapcontext technically does not return, but program may swap context to // "oucp" later, that would look as if swapcontext() returned 0. // We need to clear shadow for ucp once again, as it may be in arbitrary @@ -354,7 +390,7 @@ INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException, INTERCEPTOR(char*, index, const char *string, int c) ALIAS(WRAPPER_NAME(strchr)); # else -# if SANITIZER_MAC +# if SANITIZER_APPLE DECLARE_REAL(char*, index, const char *string, int c) OVERRIDE_FUNCTION(index, strchr); # else @@ -370,9 +406,9 @@ DEFINE_REAL(char*, index, const char *string, int c) ASAN_INTERCEPTOR_ENTER(ctx, strcat); ENSURE_ASAN_INITED(); if (flags()->replace_str) { - uptr from_length = REAL(strlen)(from); + uptr from_length = internal_strlen(from); ASAN_READ_RANGE(ctx, from, from_length + 1); - uptr to_length = REAL(strlen)(to); + uptr to_length = internal_strlen(to); ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); // If the copying actually happens, the |from| string should not overlap @@ -394,7 +430,7 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { uptr from_length = MaybeRealStrnlen(from, size); uptr copy_length = Min(size, from_length + 1); ASAN_READ_RANGE(ctx, from, copy_length); - uptr to_length = REAL(strlen)(to); + uptr to_length = internal_strlen(to); ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); if (from_length > 0) { @@ -408,7 +444,7 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { INTERCEPTOR(char *, strcpy, char *to, const char *from) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strcpy); -#if SANITIZER_MAC +#if SANITIZER_APPLE if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); #endif @@ -419,7 +455,7 @@ INTERCEPTOR(char *, strcpy, char *to, const char *from) { } ENSURE_ASAN_INITED(); if (flags()->replace_str) { - uptr from_size = REAL(strlen)(from) + 1; + uptr from_size = internal_strlen(from) + 1; CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); ASAN_READ_RANGE(ctx, from, from_size); ASAN_WRITE_RANGE(ctx, to, from_size); @@ -432,7 +468,7 @@ INTERCEPTOR(char*, strdup, const char *s) { ASAN_INTERCEPTOR_ENTER(ctx, strdup); if (UNLIKELY(!asan_inited)) return internal_strdup(s); ENSURE_ASAN_INITED(); - uptr length = REAL(strlen)(s); + uptr length = internal_strlen(s); if (flags()->replace_str) { ASAN_READ_RANGE(ctx, s, length + 1); } @@ -448,7 +484,7 @@ INTERCEPTOR(char*, __strdup, const char *s) { ASAN_INTERCEPTOR_ENTER(ctx, strdup); if (UNLIKELY(!asan_inited)) return internal_strdup(s); ENSURE_ASAN_INITED(); - uptr length = REAL(strlen)(s); + uptr length = internal_strlen(s); if (flags()->replace_str) { ASAN_READ_RANGE(ctx, s, length + 1); } @@ -488,7 +524,7 @@ INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) { INTERCEPTOR(int, atoi, const char *nptr) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, atoi); -#if SANITIZER_MAC +#if SANITIZER_APPLE if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr); #endif ENSURE_ASAN_INITED(); @@ -509,7 +545,7 @@ INTERCEPTOR(int, atoi, const char *nptr) { INTERCEPTOR(long, atol, const char *nptr) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, atol); -#if SANITIZER_MAC +#if SANITIZER_APPLE if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr); #endif ENSURE_ASAN_INITED(); @@ -562,7 +598,7 @@ static void AtCxaAtexit(void *unused) { #if ASAN_INTERCEPT___CXA_ATEXIT INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, void *dso_handle) { -#if SANITIZER_MAC +#if SANITIZER_APPLE if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle); #endif ENSURE_ASAN_INITED(); @@ -581,7 +617,7 @@ INTERCEPTOR(int, atexit, void (*func)()) { #if CAN_SANITIZE_LEAKS __lsan::ScopedInterceptorDisabler disabler; #endif - // Avoid calling real atexit as it is unrechable on at least on Linux. + // Avoid calling real atexit as it is unreachable on at least on Linux. int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr); REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); return res; @@ -643,10 +679,11 @@ void InitializeAsanInterceptors() { // Intecept jump-related functions. ASAN_INTERCEPT_FUNC(longjmp); -#if ASAN_INTERCEPT_SWAPCONTEXT +# if ASAN_INTERCEPT_SWAPCONTEXT ASAN_INTERCEPT_FUNC(swapcontext); -#endif -#if ASAN_INTERCEPT__LONGJMP + ASAN_INTERCEPT_FUNC(makecontext); +# endif +# if ASAN_INTERCEPT__LONGJMP ASAN_INTERCEPT_FUNC(_longjmp); #endif #if ASAN_INTERCEPT___LONGJMP_CHK diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_interceptors.h b/gnu/llvm/compiler-rt/lib/asan/asan_interceptors.h index a9249dea45b..c4bf087ea17 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_interceptors.h +++ b/gnu/llvm/compiler-rt/lib/asan/asan_interceptors.h @@ -114,7 +114,7 @@ void InitializePlatformInterceptors(); #if SANITIZER_LINUX && \ (defined(__arm__) || defined(__aarch64__) || defined(__i386__) || \ - defined(__x86_64__) || SANITIZER_RISCV64) + defined(__x86_64__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64) # define ASAN_INTERCEPT_VFORK 1 #else # define ASAN_INTERCEPT_VFORK 0 @@ -133,29 +133,30 @@ DECLARE_REAL(char*, strncpy, char *to, const char *from, uptr size) DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen) DECLARE_REAL(char*, strstr, const char *s1, const char *s2) -#if !SANITIZER_MAC -#define ASAN_INTERCEPT_FUNC(name) \ - do { \ - if (!INTERCEPT_FUNCTION(name)) \ - VReport(1, "AddressSanitizer: failed to intercept '%s'\n", #name); \ - } while (0) -#define ASAN_INTERCEPT_FUNC_VER(name, ver) \ - do { \ - if (!INTERCEPT_FUNCTION_VER(name, ver)) \ - VReport(1, "AddressSanitizer: failed to intercept '%s@@%s'\n", #name, \ - #ver); \ - } while (0) -#define ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \ - do { \ - if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \ - VReport(1, "AddressSanitizer: failed to intercept '%s@@%s' or '%s'\n", \ - #name, #ver, #name); \ - } while (0) - -#else +# if !SANITIZER_APPLE +# define ASAN_INTERCEPT_FUNC(name) \ + do { \ + if (!INTERCEPT_FUNCTION(name)) \ + VReport(1, "AddressSanitizer: failed to intercept '%s'\n", #name); \ + } while (0) +# define ASAN_INTERCEPT_FUNC_VER(name, ver) \ + do { \ + if (!INTERCEPT_FUNCTION_VER(name, ver)) \ + VReport(1, "AddressSanitizer: failed to intercept '%s@@%s'\n", \ + #name, ver); \ + } while (0) +# define ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \ + do { \ + if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \ + VReport(1, \ + "AddressSanitizer: failed to intercept '%s@@%s' or '%s'\n", \ + #name, ver, #name); \ + } while (0) + +# else // OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION. -#define ASAN_INTERCEPT_FUNC(name) -#endif // SANITIZER_MAC +# define ASAN_INTERCEPT_FUNC(name) +# endif // SANITIZER_APPLE #endif // !SANITIZER_FUCHSIA diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_interceptors_memintrinsics.h b/gnu/llvm/compiler-rt/lib/asan/asan_interceptors_memintrinsics.h index 632f0515a9e..bbc5390ceaa 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_interceptors_memintrinsics.h +++ b/gnu/llvm/compiler-rt/lib/asan/asan_interceptors_memintrinsics.h @@ -18,26 +18,29 @@ #include "asan_mapping.h" #include "interception/interception.h" -DECLARE_REAL(void*, memcpy, void *to, const void *from, uptr size) -DECLARE_REAL(void*, memset, void *block, int c, uptr size) +DECLARE_REAL(void *, memcpy, void *to, const void *from, uptr size) +DECLARE_REAL(void *, memset, void *block, int c, uptr size) namespace __asan { // Return true if we can quickly decide that the region is unpoisoned. // We assume that a redzone is at least 16 bytes. static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) { - if (size == 0) return true; - if (size <= 32) - return !AddressIsPoisoned(beg) && - !AddressIsPoisoned(beg + size - 1) && - !AddressIsPoisoned(beg + size / 2); - if (size <= 64) - return !AddressIsPoisoned(beg) && - !AddressIsPoisoned(beg + size / 4) && - !AddressIsPoisoned(beg + size - 1) && - !AddressIsPoisoned(beg + 3 * size / 4) && - !AddressIsPoisoned(beg + size / 2); - return false; + if (UNLIKELY(size == 0 || size > sizeof(uptr) * ASAN_SHADOW_GRANULARITY)) + return !size; + + uptr last = beg + size - 1; + uptr shadow_first = MEM_TO_SHADOW(beg); + uptr shadow_last = MEM_TO_SHADOW(last); + uptr uptr_first = RoundDownTo(shadow_first, sizeof(uptr)); + uptr uptr_last = RoundDownTo(shadow_last, sizeof(uptr)); + if (LIKELY(((*reinterpret_cast(uptr_first) | + *reinterpret_cast(uptr_last)) == 0))) + return true; + u8 shadow = AddressIsPoisoned(last); + for (; shadow_first < shadow_last; ++shadow_first) + shadow |= *((u8 *)shadow_first); + return !shadow; } struct AsanInterceptorContext { @@ -49,75 +52,68 @@ struct AsanInterceptorContext { // that no extra frames are created, and stack trace contains // relevant information only. // We check all shadow bytes. -#define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) do { \ - uptr __offset = (uptr)(offset); \ - uptr __size = (uptr)(size); \ - uptr __bad = 0; \ - if (__offset > __offset + __size) { \ - GET_STACK_TRACE_FATAL_HERE; \ - ReportStringFunctionSizeOverflow(__offset, __size, &stack); \ - } \ - if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \ - (__bad = __asan_region_is_poisoned(__offset, __size))) { \ - AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \ - bool suppressed = false; \ - if (_ctx) { \ - suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \ - if (!suppressed && HaveStackTraceBasedSuppressions()) { \ - GET_STACK_TRACE_FATAL_HERE; \ - suppressed = IsStackTraceSuppressed(&stack); \ - } \ - } \ - if (!suppressed) { \ - GET_CURRENT_PC_BP_SP; \ - ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false);\ - } \ - } \ +#define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) \ + do { \ + uptr __offset = (uptr)(offset); \ + uptr __size = (uptr)(size); \ + uptr __bad = 0; \ + if (UNLIKELY(__offset > __offset + __size)) { \ + GET_STACK_TRACE_FATAL_HERE; \ + ReportStringFunctionSizeOverflow(__offset, __size, &stack); \ + } \ + if (UNLIKELY(!QuickCheckForUnpoisonedRegion(__offset, __size)) && \ + (__bad = __asan_region_is_poisoned(__offset, __size))) { \ + AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \ + bool suppressed = false; \ + if (_ctx) { \ + suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \ + if (!suppressed && HaveStackTraceBasedSuppressions()) { \ + GET_STACK_TRACE_FATAL_HERE; \ + suppressed = IsStackTraceSuppressed(&stack); \ + } \ + } \ + if (!suppressed) { \ + GET_CURRENT_PC_BP_SP; \ + ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false); \ + } \ + } \ } while (0) // memcpy is called during __asan_init() from the internals of printf(...). // We do not treat memcpy with to==from as a bug. // See http://llvm.org/bugs/show_bug.cgi?id=11763. -#define ASAN_MEMCPY_IMPL(ctx, to, from, size) \ - do { \ - if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size); \ - if (asan_init_is_running) { \ - return REAL(memcpy)(to, from, size); \ - } \ - ENSURE_ASAN_INITED(); \ - if (flags()->replace_intrin) { \ - if (to != from) { \ - CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \ - } \ - ASAN_READ_RANGE(ctx, from, size); \ - ASAN_WRITE_RANGE(ctx, to, size); \ - } \ - return REAL(memcpy)(to, from, size); \ +#define ASAN_MEMCPY_IMPL(ctx, to, from, size) \ + do { \ + if (LIKELY(replace_intrin_cached)) { \ + if (LIKELY(to != from)) { \ + CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \ + } \ + ASAN_READ_RANGE(ctx, from, size); \ + ASAN_WRITE_RANGE(ctx, to, size); \ + } else if (UNLIKELY(!asan_inited)) { \ + return internal_memcpy(to, from, size); \ + } \ + return REAL(memcpy)(to, from, size); \ } while (0) // memset is called inside Printf. -#define ASAN_MEMSET_IMPL(ctx, block, c, size) \ - do { \ - if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size); \ - if (asan_init_is_running) { \ - return REAL(memset)(block, c, size); \ - } \ - ENSURE_ASAN_INITED(); \ - if (flags()->replace_intrin) { \ - ASAN_WRITE_RANGE(ctx, block, size); \ - } \ - return REAL(memset)(block, c, size); \ +#define ASAN_MEMSET_IMPL(ctx, block, c, size) \ + do { \ + if (LIKELY(replace_intrin_cached)) { \ + ASAN_WRITE_RANGE(ctx, block, size); \ + } else if (UNLIKELY(!asan_inited)) { \ + return internal_memset(block, c, size); \ + } \ + return REAL(memset)(block, c, size); \ } while (0) -#define ASAN_MEMMOVE_IMPL(ctx, to, from, size) \ - do { \ - if (UNLIKELY(!asan_inited)) return internal_memmove(to, from, size); \ - ENSURE_ASAN_INITED(); \ - if (flags()->replace_intrin) { \ - ASAN_READ_RANGE(ctx, from, size); \ - ASAN_WRITE_RANGE(ctx, to, size); \ - } \ - return internal_memmove(to, from, size); \ +#define ASAN_MEMMOVE_IMPL(ctx, to, from, size) \ + do { \ + if (LIKELY(replace_intrin_cached)) { \ + ASAN_READ_RANGE(ctx, from, size); \ + ASAN_WRITE_RANGE(ctx, to, size); \ + } \ + return internal_memmove(to, from, size); \ } while (0) #define ASAN_READ_RANGE(ctx, offset, size) \ @@ -136,7 +132,7 @@ static inline bool RangesOverlap(const char *offset1, uptr length1, do { \ const char *offset1 = (const char *)_offset1; \ const char *offset2 = (const char *)_offset2; \ - if (RangesOverlap(offset1, length1, offset2, length2)) { \ + if (UNLIKELY(RangesOverlap(offset1, length1, offset2, length2))) { \ GET_STACK_TRACE_FATAL_HERE; \ bool suppressed = IsInterceptorSuppressed(name); \ if (!suppressed && HaveStackTraceBasedSuppressions()) { \ diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_interceptors_vfork.S b/gnu/llvm/compiler-rt/lib/asan/asan_interceptors_vfork.S index 3ae5503e83c..ec29adc7b13 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_interceptors_vfork.S +++ b/gnu/llvm/compiler-rt/lib/asan/asan_interceptors_vfork.S @@ -6,6 +6,7 @@ #include "sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S" #include "sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S" #include "sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S" +#include "sanitizer_common/sanitizer_common_interceptors_vfork_loongarch64.inc.S" #include "sanitizer_common/sanitizer_common_interceptors_vfork_riscv64.inc.S" #include "sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S" #endif diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_interface.inc b/gnu/llvm/compiler-rt/lib/asan/asan_interface.inc index ea28fc8ae87..bfc44b46196 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_interface.inc +++ b/gnu/llvm/compiler-rt/lib/asan/asan_interface.inc @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// // Asan interface list. //===----------------------------------------------------------------------===// + INTERFACE_FUNCTION(__asan_addr_is_in_fake_stack) INTERFACE_FUNCTION(__asan_address_is_poisoned) INTERFACE_FUNCTION(__asan_after_dynamic_init) @@ -107,6 +108,13 @@ INTERFACE_FUNCTION(__asan_report_store_n_noabort) INTERFACE_FUNCTION(__asan_set_death_callback) INTERFACE_FUNCTION(__asan_set_error_report_callback) INTERFACE_FUNCTION(__asan_set_shadow_00) +INTERFACE_FUNCTION(__asan_set_shadow_01) +INTERFACE_FUNCTION(__asan_set_shadow_02) +INTERFACE_FUNCTION(__asan_set_shadow_03) +INTERFACE_FUNCTION(__asan_set_shadow_04) +INTERFACE_FUNCTION(__asan_set_shadow_05) +INTERFACE_FUNCTION(__asan_set_shadow_06) +INTERFACE_FUNCTION(__asan_set_shadow_07) INTERFACE_FUNCTION(__asan_set_shadow_f1) INTERFACE_FUNCTION(__asan_set_shadow_f2) INTERFACE_FUNCTION(__asan_set_shadow_f3) diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_interface_internal.h b/gnu/llvm/compiler-rt/lib/asan/asan_interface_internal.h index 3e6e6602887..987f855c0f9 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_interface_internal.h +++ b/gnu/llvm/compiler-rt/lib/asan/asan_interface_internal.h @@ -53,8 +53,9 @@ extern "C" { const char *module_name; // Module name as a C string. This pointer is a // unique identifier of a module. uptr has_dynamic_init; // Non-zero if the global has dynamic initializer. - __asan_global_source_location *location; // Source location of a global, - // or NULL if it is unknown. + uptr windows_padding; // TODO: Figure out how to remove this padding + // that's simply here to make the MSVC incremental + // linker happy... uptr odr_indicator; // The address of the ODR indicator symbol. }; @@ -89,6 +90,20 @@ extern "C" { SANITIZER_INTERFACE_ATTRIBUTE void __asan_set_shadow_00(uptr addr, uptr size); SANITIZER_INTERFACE_ATTRIBUTE + void __asan_set_shadow_01(uptr addr, uptr size); + SANITIZER_INTERFACE_ATTRIBUTE + void __asan_set_shadow_02(uptr addr, uptr size); + SANITIZER_INTERFACE_ATTRIBUTE + void __asan_set_shadow_03(uptr addr, uptr size); + SANITIZER_INTERFACE_ATTRIBUTE + void __asan_set_shadow_04(uptr addr, uptr size); + SANITIZER_INTERFACE_ATTRIBUTE + void __asan_set_shadow_05(uptr addr, uptr size); + SANITIZER_INTERFACE_ATTRIBUTE + void __asan_set_shadow_06(uptr addr, uptr size); + SANITIZER_INTERFACE_ATTRIBUTE + void __asan_set_shadow_07(uptr addr, uptr size); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_set_shadow_f1(uptr addr, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void __asan_set_shadow_f2(uptr addr, uptr size); diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_internal.h b/gnu/llvm/compiler-rt/lib/asan/asan_internal.h index ad3320304d0..a5348e35b29 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_internal.h +++ b/gnu/llvm/compiler-rt/lib/asan/asan_internal.h @@ -17,19 +17,19 @@ #include "asan_interface_internal.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_internal_defs.h" -#include "sanitizer_common/sanitizer_stacktrace.h" #include "sanitizer_common/sanitizer_libc.h" +#include "sanitizer_common/sanitizer_stacktrace.h" #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) -# error "The AddressSanitizer run-time should not be" - " instrumented by AddressSanitizer" +# error \ + "The AddressSanitizer run-time should not be instrumented by AddressSanitizer" #endif // Build-time configuration options. // If set, asan will intercept C++ exception api call(s). #ifndef ASAN_HAS_EXCEPTIONS -# define ASAN_HAS_EXCEPTIONS 1 +# define ASAN_HAS_EXCEPTIONS 1 #endif // If set, values like allocator chunk size, as well as defaults for some flags @@ -43,11 +43,11 @@ #endif #ifndef ASAN_DYNAMIC -# ifdef PIC -# define ASAN_DYNAMIC 1 -# else -# define ASAN_DYNAMIC 0 -# endif +# ifdef PIC +# define ASAN_DYNAMIC 1 +# else +# define ASAN_DYNAMIC 0 +# endif #endif // All internal functions in asan reside inside the __asan namespace @@ -105,6 +105,7 @@ void AsanApplyToGlobals(globals_op_fptr op, const void *needle); void AsanOnDeadlySignal(int, void *siginfo, void *context); +void SignContextStack(void *context); void ReadContextStack(void *context, uptr *stack, uptr *ssize); void StopInitOrderChecking(); @@ -123,26 +124,19 @@ void *AsanDlSymNext(const char *sym); // `dlopen()` specific initialization inside this function. bool HandleDlopenInit(); -// Add convenient macro for interface functions that may be represented as -// weak hooks. -#define ASAN_MALLOC_HOOK(ptr, size) \ - do { \ - if (&__sanitizer_malloc_hook) __sanitizer_malloc_hook(ptr, size); \ - RunMallocHooks(ptr, size); \ - } while (false) -#define ASAN_FREE_HOOK(ptr) \ - do { \ - if (&__sanitizer_free_hook) __sanitizer_free_hook(ptr); \ - RunFreeHooks(ptr); \ - } while (false) +void InstallAtExitCheckLeaks(); + #define ASAN_ON_ERROR() \ - if (&__asan_on_error) __asan_on_error() + if (&__asan_on_error) \ + __asan_on_error() extern int asan_inited; // Used to avoid infinite recursion in __asan_init(). extern bool asan_init_is_running; +extern bool replace_intrin_cached; extern void (*death_callback)(void); -// These magic values are written to shadow for better error reporting. +// These magic values are written to shadow for better error +// reporting. const int kAsanHeapLeftRedzoneMagic = 0xfa; const int kAsanHeapFreeMagic = 0xfd; const int kAsanStackLeftRedzoneMagic = 0xf1; diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_linux.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_linux.cpp index 4bcbe5d02e3..e19b4479aaf 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_linux.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_linux.cpp @@ -15,55 +15,56 @@ #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ SANITIZER_SOLARIS -#include "asan_interceptors.h" -#include "asan_internal.h" -#include "asan_premap_shadow.h" -#include "asan_thread.h" -#include "sanitizer_common/sanitizer_flags.h" -#include "sanitizer_common/sanitizer_freebsd.h" -#include "sanitizer_common/sanitizer_libc.h" -#include "sanitizer_common/sanitizer_procmaps.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if SANITIZER_FREEBSD -#include -#endif - -#if SANITIZER_SOLARIS -#include -#endif - -#if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS -#include -extern "C" void* _DYNAMIC; -#elif SANITIZER_NETBSD -#include -#include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include "asan_interceptors.h" +# include "asan_internal.h" +# include "asan_premap_shadow.h" +# include "asan_thread.h" +# include "sanitizer_common/sanitizer_flags.h" +# include "sanitizer_common/sanitizer_freebsd.h" +# include "sanitizer_common/sanitizer_hash.h" +# include "sanitizer_common/sanitizer_libc.h" +# include "sanitizer_common/sanitizer_procmaps.h" + +# if SANITIZER_FREEBSD +# include +# endif + +# if SANITIZER_SOLARIS +# include +# endif + +# if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS +# include +extern "C" void *_DYNAMIC; +# elif SANITIZER_NETBSD +# include +# include extern Elf_Dyn _DYNAMIC; -#else -#include -#include +# else +# include +# include extern ElfW(Dyn) _DYNAMIC[]; -#endif +# endif // x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in // 32-bit mode. -#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \ - __FreeBSD_version <= 902001 // v9.2 -#define ucontext_t xucontext_t -#endif +# if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \ + __FreeBSD_version <= 902001 // v9.2 +# define ucontext_t xucontext_t +# endif typedef enum { ASAN_RT_VERSION_UNDEFINED = 0, @@ -74,21 +75,21 @@ typedef enum { // FIXME: perhaps also store abi version here? extern "C" { SANITIZER_INTERFACE_ATTRIBUTE -asan_rt_version_t __asan_rt_version; +asan_rt_version_t __asan_rt_version; } namespace __asan { void InitializePlatformInterceptors() {} void InitializePlatformExceptionHandlers() {} -bool IsSystemHeapAddress (uptr addr) { return false; } +bool IsSystemHeapAddress(uptr addr) { return false; } void *AsanDoesNotSupportStaticLinkage() { // This will fail to link with -static. return &_DYNAMIC; } -#if ASAN_PREMAP_SHADOW +# if ASAN_PREMAP_SHADOW uptr FindPremappedShadowStart(uptr shadow_size_bytes) { uptr granularity = GetMmapGranularity(); uptr shadow_start = reinterpret_cast(&__asan_shadow); @@ -98,16 +99,16 @@ uptr FindPremappedShadowStart(uptr shadow_size_bytes) { UnmapFromTo(shadow_start + shadow_size, shadow_start + premap_shadow_size); return shadow_start; } -#endif +# endif uptr FindDynamicShadowStart() { uptr shadow_size_bytes = MemToShadowSize(kHighMemEnd); -#if ASAN_PREMAP_SHADOW +# if ASAN_PREMAP_SHADOW if (!PremapShadowFailed()) return FindPremappedShadowStart(shadow_size_bytes); -#endif +# endif - return MapDynamicShadow(shadow_size_bytes, SHADOW_SCALE, + return MapDynamicShadow(shadow_size_bytes, ASAN_SHADOW_SCALE, /*min_shadow_base_alignment*/ 0, kHighMemEnd); } @@ -121,46 +122,40 @@ void FlushUnneededASanShadowMemory(uptr p, uptr size) { ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size)); } -#if SANITIZER_ANDROID +# if SANITIZER_ANDROID // FIXME: should we do anything for Android? void AsanCheckDynamicRTPrereqs() {} void AsanCheckIncompatibleRT() {} -#else +# else static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size, void *data) { - VReport(2, "info->dlpi_name = %s\tinfo->dlpi_addr = %p\n", - info->dlpi_name, info->dlpi_addr); + VReport(2, "info->dlpi_name = %s\tinfo->dlpi_addr = %p\n", info->dlpi_name, + (void *)info->dlpi_addr); - // Continue until the first dynamic library is found - if (!info->dlpi_name || info->dlpi_name[0] == 0) - return 0; - - // Ignore vDSO - if (internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0) - return 0; + const char **name = (const char **)data; -#if SANITIZER_FREEBSD || SANITIZER_NETBSD // Ignore first entry (the main program) - char **p = (char **)data; - if (!(*p)) { - *p = (char *)-1; + if (!*name) { + *name = ""; return 0; } -#endif -#if SANITIZER_SOLARIS - // Ignore executable on Solaris - if (info->dlpi_addr == 0) +# if SANITIZER_LINUX + // Ignore vDSO. glibc versions earlier than 2.15 (and some patched + // by distributors) return an empty name for the vDSO entry, so + // detect this as well. + if (!info->dlpi_name[0] || + internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0) return 0; -#endif +# endif - *(const char **)data = info->dlpi_name; + *name = info->dlpi_name; return 1; } static bool IsDynamicRTName(const char *libname) { return internal_strstr(libname, "libclang_rt.asan") || - internal_strstr(libname, "libasan.so"); + internal_strstr(libname, "libasan.so"); } static void ReportIncompatibleRT() { @@ -175,10 +170,11 @@ void AsanCheckDynamicRTPrereqs() { // Ensure that dynamic RT is the first DSO in the list const char *first_dso_name = nullptr; dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name); - if (first_dso_name && !IsDynamicRTName(first_dso_name)) { - Report("ASan runtime does not come first in initial library list; " - "you should either link runtime to your application or " - "manually preload it with LD_PRELOAD.\n"); + if (first_dso_name && first_dso_name[0] && !IsDynamicRTName(first_dso_name)) { + Report( + "ASan runtime does not come first in initial library list; " + "you should either link runtime to your application or " + "manually preload it with LD_PRELOAD.\n"); Die(); } } @@ -196,13 +192,14 @@ void AsanCheckIncompatibleRT() { // as early as possible, otherwise ASan interceptors could bind to // the functions in dynamic ASan runtime instead of the functions in // system libraries, causing crashes later in ASan initialization. - MemoryMappingLayout proc_maps(/*cache_enabled*/true); + MemoryMappingLayout proc_maps(/*cache_enabled*/ true); char filename[PATH_MAX]; MemoryMappedSegment segment(filename, sizeof(filename)); while (proc_maps.Next(&segment)) { if (IsDynamicRTName(segment.filename)) { - Report("Your application is linked against " - "incompatible ASan runtimes.\n"); + Report( + "Your application is linked against " + "incompatible ASan runtimes.\n"); Die(); } } @@ -212,23 +209,36 @@ void AsanCheckIncompatibleRT() { } } } -#endif // SANITIZER_ANDROID +# endif // SANITIZER_ANDROID -#if !SANITIZER_ANDROID -void ReadContextStack(void *context, uptr *stack, uptr *ssize) { - ucontext_t *ucp = (ucontext_t*)context; - *stack = (uptr)ucp->uc_stack.ss_sp; - *ssize = ucp->uc_stack.ss_size; +# if ASAN_INTERCEPT_SWAPCONTEXT +constexpr u32 kAsanContextStackFlagsMagic = 0x51260eea; + +static int HashContextStack(const ucontext_t &ucp) { + MurMur2Hash64Builder hash(kAsanContextStackFlagsMagic); + hash.add(reinterpret_cast(ucp.uc_stack.ss_sp)); + hash.add(ucp.uc_stack.ss_size); + return static_cast(hash.get()); } -#else -void ReadContextStack(void *context, uptr *stack, uptr *ssize) { - UNIMPLEMENTED(); + +void SignContextStack(void *context) { + ucontext_t *ucp = reinterpret_cast(context); + ucp->uc_stack.ss_flags = HashContextStack(*ucp); } -#endif -void *AsanDlSymNext(const char *sym) { - return dlsym(RTLD_NEXT, sym); +void ReadContextStack(void *context, uptr *stack, uptr *ssize) { + const ucontext_t *ucp = reinterpret_cast(context); + if (HashContextStack(*ucp) == ucp->uc_stack.ss_flags) { + *stack = reinterpret_cast(ucp->uc_stack.ss_sp); + *ssize = ucp->uc_stack.ss_size; + return; + } + *stack = 0; + *ssize = 0; } +# endif // ASAN_INTERCEPT_SWAPCONTEXT + +void *AsanDlSymNext(const char *sym) { return dlsym(RTLD_NEXT, sym); } bool HandleDlopenInit() { // Not supported on this platform. @@ -237,7 +247,7 @@ bool HandleDlopenInit() { return false; } -} // namespace __asan +} // namespace __asan #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || // SANITIZER_SOLARIS diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_mac.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_mac.cpp index c6950547f08..c9bd5fb8e1a 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_mac.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_mac.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_platform.h" -#if SANITIZER_MAC +#if SANITIZER_APPLE #include "asan_interceptors.h" #include "asan_internal.h" @@ -55,7 +55,7 @@ void *AsanDoesNotSupportStaticLinkage() { } uptr FindDynamicShadowStart() { - return MapDynamicShadow(MemToShadowSize(kHighMemEnd), SHADOW_SCALE, + return MapDynamicShadow(MemToShadowSize(kHighMemEnd), ASAN_SHADOW_SCALE, /*min_shadow_base_alignment*/ 0, kHighMemEnd); } @@ -95,10 +95,6 @@ void FlushUnneededASanShadowMemory(uptr p, uptr size) { ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size)); } -void ReadContextStack(void *context, uptr *stack, uptr *ssize) { - UNIMPLEMENTED(); -} - // Support for the following functions from libdispatch on Mac OS: // dispatch_async_f() // dispatch_async() @@ -296,4 +292,4 @@ INTERCEPTOR(void, dispatch_source_set_event_handler, } #endif -#endif // SANITIZER_MAC +#endif // SANITIZER_APPLE diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_malloc_linux.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_malloc_linux.cpp index c6bec8551bc..bab80b96f58 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_malloc_linux.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_malloc_linux.cpp @@ -21,129 +21,66 @@ # include "asan_interceptors.h" # include "asan_internal.h" # include "asan_stack.h" +# include "lsan/lsan_common.h" # include "sanitizer_common/sanitizer_allocator_checks.h" +# include "sanitizer_common/sanitizer_allocator_dlsym.h" # include "sanitizer_common/sanitizer_errno.h" # include "sanitizer_common/sanitizer_tls_get_addr.h" // ---------------------- Replacement functions ---------------- {{{1 using namespace __asan; -static uptr allocated_for_dlsym; -static uptr last_dlsym_alloc_size_in_words; -static const uptr kDlsymAllocPoolSize = 1024; -static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize]; - -static inline bool IsInDlsymAllocPool(const void *ptr) { - uptr off = (uptr)ptr - (uptr)alloc_memory_for_dlsym; - return off < allocated_for_dlsym * sizeof(alloc_memory_for_dlsym[0]); -} - -static void *AllocateFromLocalPool(uptr size_in_bytes) { - uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize; - void *mem = (void*)&alloc_memory_for_dlsym[allocated_for_dlsym]; - last_dlsym_alloc_size_in_words = size_in_words; - allocated_for_dlsym += size_in_words; - CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize); - return mem; -} - -static void DeallocateFromLocalPool(const void *ptr) { - // Hack: since glibc 2.27 dlsym no longer uses stack-allocated memory to store - // error messages and instead uses malloc followed by free. To avoid pool - // exhaustion due to long object filenames, handle that special case here. - uptr prev_offset = allocated_for_dlsym - last_dlsym_alloc_size_in_words; - void *prev_mem = (void*)&alloc_memory_for_dlsym[prev_offset]; - if (prev_mem == ptr) { - REAL(memset)(prev_mem, 0, last_dlsym_alloc_size_in_words * kWordSize); - allocated_for_dlsym = prev_offset; - last_dlsym_alloc_size_in_words = 0; +struct DlsymAlloc : public DlSymAllocator { + static bool UseImpl() { return asan_init_is_running; } + static void OnAllocate(const void *ptr, uptr size) { +# if CAN_SANITIZE_LEAKS + // Suppress leaks from dlerror(). Previously dlsym hack on global array was + // used by leak sanitizer as a root region. + __lsan_register_root_region(ptr, size); +# endif } -} - -static int PosixMemalignFromLocalPool(void **memptr, uptr alignment, - uptr size_in_bytes) { - if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) - return errno_EINVAL; - - CHECK(alignment >= kWordSize); - - uptr addr = (uptr)&alloc_memory_for_dlsym[allocated_for_dlsym]; - uptr aligned_addr = RoundUpTo(addr, alignment); - uptr aligned_size = RoundUpTo(size_in_bytes, kWordSize); - - uptr *end_mem = (uptr*)(aligned_addr + aligned_size); - uptr allocated = end_mem - alloc_memory_for_dlsym; - if (allocated >= kDlsymAllocPoolSize) - return errno_ENOMEM; - - allocated_for_dlsym = allocated; - *memptr = (void*)aligned_addr; - return 0; -} - -static inline bool MaybeInDlsym() { - // Fuchsia doesn't use dlsym-based interceptors. - return !SANITIZER_FUCHSIA && asan_init_is_running; -} - -static inline bool UseLocalPool() { return MaybeInDlsym(); } - -static void *ReallocFromLocalPool(void *ptr, uptr size) { - const uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym; - const uptr copy_size = Min(size, kDlsymAllocPoolSize - offset); - void *new_ptr; - if (UNLIKELY(UseLocalPool())) { - new_ptr = AllocateFromLocalPool(size); - } else { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - new_ptr = asan_malloc(size, &stack); + static void OnFree(const void *ptr, uptr size) { +# if CAN_SANITIZE_LEAKS + __lsan_unregister_root_region(ptr, size); +# endif } - internal_memcpy(new_ptr, ptr, copy_size); - return new_ptr; -} +}; INTERCEPTOR(void, free, void *ptr) { - if (UNLIKELY(IsInDlsymAllocPool(ptr))) { - DeallocateFromLocalPool(ptr); - return; - } + if (DlsymAlloc::PointerIsMine(ptr)) + return DlsymAlloc::Free(ptr); GET_STACK_TRACE_FREE; asan_free(ptr, &stack, FROM_MALLOC); } #if SANITIZER_INTERCEPT_CFREE INTERCEPTOR(void, cfree, void *ptr) { - if (UNLIKELY(IsInDlsymAllocPool(ptr))) - return; + if (DlsymAlloc::PointerIsMine(ptr)) + return DlsymAlloc::Free(ptr); GET_STACK_TRACE_FREE; asan_free(ptr, &stack, FROM_MALLOC); } #endif // SANITIZER_INTERCEPT_CFREE INTERCEPTOR(void*, malloc, uptr size) { - if (UNLIKELY(UseLocalPool())) - // Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym. - return AllocateFromLocalPool(size); + if (DlsymAlloc::Use()) + return DlsymAlloc::Allocate(size); ENSURE_ASAN_INITED(); GET_STACK_TRACE_MALLOC; return asan_malloc(size, &stack); } INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { - if (UNLIKELY(UseLocalPool())) - // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. - return AllocateFromLocalPool(nmemb * size); + if (DlsymAlloc::Use()) + return DlsymAlloc::Callocate(nmemb, size); ENSURE_ASAN_INITED(); GET_STACK_TRACE_MALLOC; return asan_calloc(nmemb, size, &stack); } INTERCEPTOR(void*, realloc, void *ptr, uptr size) { - if (UNLIKELY(IsInDlsymAllocPool(ptr))) - return ReallocFromLocalPool(ptr, size); - if (UNLIKELY(UseLocalPool())) - return AllocateFromLocalPool(size); + if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) + return DlsymAlloc::Realloc(ptr, size); ENSURE_ASAN_INITED(); GET_STACK_TRACE_MALLOC; return asan_realloc(ptr, size, &stack); @@ -205,8 +142,6 @@ INTERCEPTOR(int, mallopt, int cmd, int value) { #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { - if (UNLIKELY(UseLocalPool())) - return PosixMemalignFromLocalPool(memptr, alignment, size); GET_STACK_TRACE_MALLOC; return asan_posix_memalign(memptr, alignment, size, &stack); } diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_malloc_mac.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_malloc_mac.cpp index e8484685dae..924d1f12640 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_malloc_mac.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_malloc_mac.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_platform.h" -#if SANITIZER_MAC +#if SANITIZER_APPLE #include "asan_interceptors.h" #include "asan_report.h" diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_mapping.h b/gnu/llvm/compiler-rt/lib/asan/asan_mapping.h index e5a7f2007ae..c5f95c07a21 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_mapping.h +++ b/gnu/llvm/compiler-rt/lib/asan/asan_mapping.h @@ -13,7 +13,7 @@ #ifndef ASAN_MAPPING_H #define ASAN_MAPPING_H -#include "asan_internal.h" +#include "sanitizer_common/sanitizer_platform.h" // The full explanation of the memory mapping could be found here: // https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm @@ -114,6 +114,13 @@ // || `[0x0080000000000, 0x008ffffffffff]` || LowShadow || // || `[0x0000000000000, 0x007ffffffffff]` || LowMem || // +// Default Linux/LoongArch64 (47-bit VMA) mapping: +// || `[0x500000000000, 0x7fffffffffff]` || HighMem || +// || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow || +// || `[0x480000000000, 0x49ffffffffff]` || ShadowGap || +// || `[0x400000000000, 0x47ffffffffff]` || LowShadow || +// || `[0x000000000000, 0x3fffffffffff]` || LowMem || +// // Shadow mapping on FreeBSD/x86-64 with SHADOW_OFFSET == 0x400000000000: // || `[0x500000000000, 0x7fffffffffff]` || HighMem || // || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow || @@ -151,149 +158,151 @@ // || `[0x30000000, 0x35ffffff]` || LowShadow || // || `[0x00000000, 0x2fffffff]` || LowMem || -#if defined(ASAN_SHADOW_SCALE) -static const u64 kDefaultShadowScale = ASAN_SHADOW_SCALE; -#else -static const u64 kDefaultShadowScale = 3; -#endif -static const u64 kDefaultShadowSentinel = ~(uptr)0; -static const u64 kDefaultShadowOffset32 = 1ULL << 29; // 0x20000000 -static const u64 kDefaultShadowOffset64 = 1ULL << 44; -static const u64 kDefaultShort64bitShadowOffset = - 0x7FFFFFFF & (~0xFFFULL << kDefaultShadowScale); // < 2G. -static const u64 kAArch64_ShadowOffset64 = 1ULL << 36; -static const u64 kRiscv64_ShadowOffset64 = 0xd55550000; -static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000; -static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37; -static const u64 kPPC64_ShadowOffset64 = 1ULL << 44; -static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52; -static const u64 kSPARC64_ShadowOffset64 = 1ULL << 43; // 0x80000000000 -static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000 -static const u64 kFreeBSD_ShadowOffset64 = 1ULL << 46; // 0x400000000000 -static const u64 kNetBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000 -static const u64 kNetBSD_ShadowOffset64 = 1ULL << 46; // 0x400000000000 -static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000 - -#define SHADOW_SCALE kDefaultShadowScale +#define ASAN_SHADOW_SCALE 3 #if SANITIZER_FUCHSIA -# define SHADOW_OFFSET (0) +# define ASAN_SHADOW_OFFSET_CONST (0) #elif SANITIZER_WORDSIZE == 32 # if SANITIZER_ANDROID -# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address +# define ASAN_SHADOW_OFFSET_DYNAMIC # elif defined(__mips__) -# define SHADOW_OFFSET kMIPS32_ShadowOffset32 +# define ASAN_SHADOW_OFFSET_CONST 0x0aaa0000 # elif SANITIZER_FREEBSD -# define SHADOW_OFFSET kFreeBSD_ShadowOffset32 +# define ASAN_SHADOW_OFFSET_CONST 0x40000000 # elif SANITIZER_NETBSD -# define SHADOW_OFFSET kNetBSD_ShadowOffset32 +# define ASAN_SHADOW_OFFSET_CONST 0x40000000 # elif SANITIZER_WINDOWS -# define SHADOW_OFFSET kWindowsShadowOffset32 +# define ASAN_SHADOW_OFFSET_CONST 0x30000000 # elif SANITIZER_IOS -# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address +# define ASAN_SHADOW_OFFSET_DYNAMIC # else -# define SHADOW_OFFSET kDefaultShadowOffset32 +# define ASAN_SHADOW_OFFSET_CONST 0x20000000 # endif #else # if SANITIZER_IOS -# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address -# elif SANITIZER_MAC && defined(__aarch64__) -# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address -#elif SANITIZER_RISCV64 -#define SHADOW_OFFSET kRiscv64_ShadowOffset64 +# define ASAN_SHADOW_OFFSET_DYNAMIC +# elif SANITIZER_APPLE && defined(__aarch64__) +# define ASAN_SHADOW_OFFSET_DYNAMIC +# elif SANITIZER_FREEBSD && defined(__aarch64__) +# define ASAN_SHADOW_OFFSET_CONST 0x0000800000000000 +# elif SANITIZER_RISCV64 +# define ASAN_SHADOW_OFFSET_CONST 0x0000000d55550000 # elif defined(__aarch64__) -# define SHADOW_OFFSET kAArch64_ShadowOffset64 +# define ASAN_SHADOW_OFFSET_CONST 0x0000001000000000 # elif defined(__powerpc64__) -# define SHADOW_OFFSET kPPC64_ShadowOffset64 +# define ASAN_SHADOW_OFFSET_CONST 0x0000100000000000 # elif defined(__s390x__) -# define SHADOW_OFFSET kSystemZ_ShadowOffset64 +# define ASAN_SHADOW_OFFSET_CONST 0x0010000000000000 # elif SANITIZER_FREEBSD -# define SHADOW_OFFSET kFreeBSD_ShadowOffset64 +# define ASAN_SHADOW_OFFSET_CONST 0x0000400000000000 # elif SANITIZER_NETBSD -# define SHADOW_OFFSET kNetBSD_ShadowOffset64 -# elif SANITIZER_MAC -# define SHADOW_OFFSET kDefaultShadowOffset64 +# define ASAN_SHADOW_OFFSET_CONST 0x0000400000000000 +# elif SANITIZER_APPLE +# define ASAN_SHADOW_OFFSET_CONST 0x0000100000000000 # elif defined(__mips64) -# define SHADOW_OFFSET kMIPS64_ShadowOffset64 -#elif defined(__sparc__) -#define SHADOW_OFFSET kSPARC64_ShadowOffset64 +# define ASAN_SHADOW_OFFSET_CONST 0x0000002000000000 +# elif defined(__sparc__) +# define ASAN_SHADOW_OFFSET_CONST 0x0000080000000000 +# elif SANITIZER_LOONGARCH64 +# define ASAN_SHADOW_OFFSET_CONST 0x0000400000000000 # elif SANITIZER_WINDOWS64 -# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address +# define ASAN_SHADOW_OFFSET_DYNAMIC # else -# define SHADOW_OFFSET kDefaultShort64bitShadowOffset +# if ASAN_SHADOW_SCALE != 3 +# error "Value below is based on shadow scale = 3." +# error "Original formula was: 0x7FFFFFFF & (~0xFFFULL << SHADOW_SCALE)." +# endif +# define ASAN_SHADOW_OFFSET_CONST 0x000000007fff8000 # endif #endif -#if SANITIZER_ANDROID && defined(__arm__) -# define ASAN_PREMAP_SHADOW 1 -#else -# define ASAN_PREMAP_SHADOW 0 -#endif +#if defined(__cplusplus) +# include "asan_internal.h" -#define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE) +static const u64 kDefaultShadowSentinel = ~(uptr)0; -#define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below. +# if defined(ASAN_SHADOW_OFFSET_CONST) +static const u64 kConstShadowOffset = ASAN_SHADOW_OFFSET_CONST; +# define ASAN_SHADOW_OFFSET kConstShadowOffset +# elif defined(ASAN_SHADOW_OFFSET_DYNAMIC) +# define ASAN_SHADOW_OFFSET __asan_shadow_memory_dynamic_address +# else +# error "ASAN_SHADOW_OFFSET can't be determined." +# endif -#if DO_ASAN_MAPPING_PROFILE -# define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++; -#else -# define PROFILE_ASAN_MAPPING() -#endif +# if SANITIZER_ANDROID && defined(__arm__) +# define ASAN_PREMAP_SHADOW 1 +# else +# define ASAN_PREMAP_SHADOW 0 +# endif + +# define ASAN_SHADOW_GRANULARITY (1ULL << ASAN_SHADOW_SCALE) + +# define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below. + +# if DO_ASAN_MAPPING_PROFILE +# define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++; +# else +# define PROFILE_ASAN_MAPPING() +# endif // If 1, all shadow boundaries are constants. // Don't set to 1 other than for testing. -#define ASAN_FIXED_MAPPING 0 +# define ASAN_FIXED_MAPPING 0 namespace __asan { extern uptr AsanMappingProfile[]; -#if ASAN_FIXED_MAPPING +# if ASAN_FIXED_MAPPING // Fixed mapping for 64-bit Linux. Mostly used for performance comparison // with non-fixed mapping. As of r175253 (Feb 2013) the performance // difference between fixed and non-fixed mapping is below the noise level. static uptr kHighMemEnd = 0x7fffffffffffULL; -static uptr kMidMemBeg = 0x3000000000ULL; -static uptr kMidMemEnd = 0x4fffffffffULL; -#else +static uptr kMidMemBeg = 0x3000000000ULL; +static uptr kMidMemEnd = 0x4fffffffffULL; +# else extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init. -#endif +# endif } // namespace __asan -#if defined(__sparc__) && SANITIZER_WORDSIZE == 64 -# include "asan_mapping_sparc64.h" -#else -#define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) + (SHADOW_OFFSET)) +# if defined(__sparc__) && SANITIZER_WORDSIZE == 64 +# include "asan_mapping_sparc64.h" +# else +# define MEM_TO_SHADOW(mem) \ + (((mem) >> ASAN_SHADOW_SCALE) + (ASAN_SHADOW_OFFSET)) +# define SHADOW_TO_MEM(mem) \ + (((mem) - (ASAN_SHADOW_OFFSET)) << (ASAN_SHADOW_SCALE)) -#define kLowMemBeg 0 -#define kLowMemEnd (SHADOW_OFFSET ? SHADOW_OFFSET - 1 : 0) +# define kLowMemBeg 0 +# define kLowMemEnd (ASAN_SHADOW_OFFSET ? ASAN_SHADOW_OFFSET - 1 : 0) -#define kLowShadowBeg SHADOW_OFFSET -#define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd) +# define kLowShadowBeg ASAN_SHADOW_OFFSET +# define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd) -#define kHighMemBeg (MEM_TO_SHADOW(kHighMemEnd) + 1) +# define kHighMemBeg (MEM_TO_SHADOW(kHighMemEnd) + 1) -#define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) -#define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd) +# define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) +# define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd) -# define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg) -# define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd) +# define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg) +# define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd) // With the zero shadow base we can not actually map pages starting from 0. // This constant is somewhat arbitrary. -#define kZeroBaseShadowStart 0 -#define kZeroBaseMaxShadowStart (1 << 18) +# define kZeroBaseShadowStart 0 +# define kZeroBaseMaxShadowStart (1 << 18) -#define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \ - : kZeroBaseShadowStart) -#define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1) +# define kShadowGapBeg \ + (kLowShadowEnd ? kLowShadowEnd + 1 : kZeroBaseShadowStart) +# define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1) -#define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0) -#define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0) +# define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0) +# define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0) -#define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0) -#define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0) +# define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0) +# define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0) namespace __asan { @@ -331,29 +340,31 @@ static inline bool AddrIsInShadowGap(uptr a) { PROFILE_ASAN_MAPPING(); if (kMidMemBeg) { if (a <= kShadowGapEnd) - return SHADOW_OFFSET == 0 || a >= kShadowGapBeg; + return ASAN_SHADOW_OFFSET == 0 || a >= kShadowGapBeg; return (a >= kShadowGap2Beg && a <= kShadowGap2End) || (a >= kShadowGap3Beg && a <= kShadowGap3End); } // In zero-based shadow mode we treat addresses near zero as addresses // in shadow gap as well. - if (SHADOW_OFFSET == 0) + if (ASAN_SHADOW_OFFSET == 0) return a <= kShadowGapEnd; return a >= kShadowGapBeg && a <= kShadowGapEnd; } } // namespace __asan -#endif +# endif namespace __asan { -static inline uptr MemToShadowSize(uptr size) { return size >> SHADOW_SCALE; } +static inline uptr MemToShadowSize(uptr size) { + return size >> ASAN_SHADOW_SCALE; +} static inline bool AddrIsInMem(uptr a) { PROFILE_ASAN_MAPPING(); return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a) || - (flags()->protect_shadow_gap == 0 && AddrIsInShadowGap(a)); + (flags()->protect_shadow_gap == 0 && AddrIsInShadowGap(a)); } static inline uptr MemToShadow(uptr p) { @@ -367,19 +378,25 @@ static inline bool AddrIsInShadow(uptr a) { return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a); } +static inline uptr ShadowToMem(uptr p) { + PROFILE_ASAN_MAPPING(); + CHECK(AddrIsInShadow(p)); + return SHADOW_TO_MEM(p); +} + static inline bool AddrIsAlignedByGranularity(uptr a) { PROFILE_ASAN_MAPPING(); - return (a & (SHADOW_GRANULARITY - 1)) == 0; + return (a & (ASAN_SHADOW_GRANULARITY - 1)) == 0; } static inline bool AddressIsPoisoned(uptr a) { PROFILE_ASAN_MAPPING(); const uptr kAccessSize = 1; - u8 *shadow_address = (u8*)MEM_TO_SHADOW(a); + u8 *shadow_address = (u8 *)MEM_TO_SHADOW(a); s8 shadow_value = *shadow_address; if (shadow_value) { - u8 last_accessed_byte = (a & (SHADOW_GRANULARITY - 1)) - + kAccessSize - 1; + u8 last_accessed_byte = + (a & (ASAN_SHADOW_GRANULARITY - 1)) + kAccessSize - 1; return (last_accessed_byte >= shadow_value); } return false; @@ -390,4 +407,6 @@ static const uptr kAsanMappingProfileSize = __LINE__; } // namespace __asan +#endif // __cplusplus + #endif // ASAN_MAPPING_H diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_mapping_sparc64.h b/gnu/llvm/compiler-rt/lib/asan/asan_mapping_sparc64.h index 432a1816f79..e310c12fe30 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_mapping_sparc64.h +++ b/gnu/llvm/compiler-rt/lib/asan/asan_mapping_sparc64.h @@ -25,13 +25,15 @@ // The idea is to chop the high bits before doing the scaling, so the two // parts become contiguous again and the usual scheme can be applied. -#define MEM_TO_SHADOW(mem) \ - ((((mem) << HIGH_BITS) >> (HIGH_BITS + (SHADOW_SCALE))) + (SHADOW_OFFSET)) +#define MEM_TO_SHADOW(mem) \ + ((((mem) << HIGH_BITS) >> (HIGH_BITS + (ASAN_SHADOW_SCALE))) + \ + (ASAN_SHADOW_OFFSET)) +#define SHADOW_TO_MEM(ptr) (__asan::ShadowToMemSparc64(ptr)) #define kLowMemBeg 0 -#define kLowMemEnd (SHADOW_OFFSET - 1) +#define kLowMemEnd (ASAN_SHADOW_OFFSET - 1) -#define kLowShadowBeg SHADOW_OFFSET +#define kLowShadowBeg ASAN_SHADOW_OFFSET #define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd) // But of course there is the huge hole between the high shadow memory, @@ -96,6 +98,24 @@ static inline bool AddrIsInShadowGap(uptr a) { return a >= kShadowGapBeg && a <= kShadowGapEnd; } +static inline constexpr uptr ShadowToMemSparc64(uptr p) { + PROFILE_ASAN_MAPPING(); + p -= ASAN_SHADOW_OFFSET; + p <<= ASAN_SHADOW_SCALE; + if (p >= 0x8000000000000) { + p |= (~0ULL) << VMA_BITS; + } + return p; +} + +static_assert(ShadowToMemSparc64(MEM_TO_SHADOW(0x0000000000000000)) == + 0x0000000000000000); +static_assert(ShadowToMemSparc64(MEM_TO_SHADOW(0xfff8000000000000)) == + 0xfff8000000000000); +// Gets aligned down. +static_assert(ShadowToMemSparc64(MEM_TO_SHADOW(0x0007ffffffffffff)) == + 0x0007fffffffffff8); + } // namespace __asan #endif // ASAN_MAPPING_SPARC64_H diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_new_delete.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_new_delete.cpp index da446072de1..17280129c75 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_new_delete.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_new_delete.cpp @@ -89,7 +89,7 @@ enum class align_val_t: size_t {}; // delete. // To make sure that C++ allocation/deallocation operators are overridden on // OS X we need to intercept them using their mangled names. -#if !SANITIZER_MAC +#if !SANITIZER_APPLE CXX_OPERATOR_ATTRIBUTE void *operator new(size_t size) { OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/); } @@ -115,7 +115,7 @@ CXX_OPERATOR_ATTRIBUTE void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) { OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/); } -#else // SANITIZER_MAC +#else // SANITIZER_APPLE INTERCEPTOR(void *, _Znwm, size_t size) { OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/); } @@ -128,7 +128,7 @@ INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) { INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/); } -#endif // !SANITIZER_MAC +#endif // !SANITIZER_APPLE #define OPERATOR_DELETE_BODY(type) \ GET_STACK_TRACE_FREE; \ @@ -146,7 +146,7 @@ INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) { GET_STACK_TRACE_FREE; \ asan_delete(ptr, size, static_cast(align), &stack, type); -#if !SANITIZER_MAC +#if !SANITIZER_APPLE CXX_OPERATOR_ATTRIBUTE void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY(FROM_NEW); } @@ -184,7 +184,7 @@ CXX_OPERATOR_ATTRIBUTE void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT { OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR); } -#else // SANITIZER_MAC +#else // SANITIZER_APPLE INTERCEPTOR(void, _ZdlPv, void *ptr) { OPERATOR_DELETE_BODY(FROM_NEW); } INTERCEPTOR(void, _ZdaPv, void *ptr) @@ -193,4 +193,4 @@ INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY(FROM_NEW); } INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY(FROM_NEW_BR); } -#endif // !SANITIZER_MAC +#endif // !SANITIZER_APPLE diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_poisoning.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_poisoning.cpp index 5f215fe0f9b..5164b7d860f 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_poisoning.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_poisoning.cpp @@ -12,11 +12,13 @@ //===----------------------------------------------------------------------===// #include "asan_poisoning.h" + #include "asan_report.h" #include "asan_stack.h" #include "sanitizer_common/sanitizer_atomic.h" -#include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_flags.h" +#include "sanitizer_common/sanitizer_interface_internal.h" +#include "sanitizer_common/sanitizer_libc.h" namespace __asan { @@ -35,7 +37,7 @@ void PoisonShadow(uptr addr, uptr size, u8 value) { CHECK(AddrIsAlignedByGranularity(addr)); CHECK(AddrIsInMem(addr)); CHECK(AddrIsAlignedByGranularity(addr + size)); - CHECK(AddrIsInMem(addr + size - SHADOW_GRANULARITY)); + CHECK(AddrIsInMem(addr + size - ASAN_SHADOW_GRANULARITY)); CHECK(REAL(memset)); FastPoisonShadow(addr, size, value); } @@ -52,12 +54,12 @@ void PoisonShadowPartialRightRedzone(uptr addr, struct ShadowSegmentEndpoint { u8 *chunk; - s8 offset; // in [0, SHADOW_GRANULARITY) + s8 offset; // in [0, ASAN_SHADOW_GRANULARITY) s8 value; // = *chunk; explicit ShadowSegmentEndpoint(uptr address) { chunk = (u8*)MemToShadow(address); - offset = address & (SHADOW_GRANULARITY - 1); + offset = address & (ASAN_SHADOW_GRANULARITY - 1); value = *chunk; } }; @@ -66,20 +68,20 @@ void AsanPoisonOrUnpoisonIntraObjectRedzone(uptr ptr, uptr size, bool poison) { uptr end = ptr + size; if (Verbosity()) { Printf("__asan_%spoison_intra_object_redzone [%p,%p) %zd\n", - poison ? "" : "un", ptr, end, size); + poison ? "" : "un", (void *)ptr, (void *)end, size); if (Verbosity() >= 2) PRINT_CURRENT_STACK(); } CHECK(size); CHECK_LE(size, 4096); - CHECK(IsAligned(end, SHADOW_GRANULARITY)); - if (!IsAligned(ptr, SHADOW_GRANULARITY)) { + CHECK(IsAligned(end, ASAN_SHADOW_GRANULARITY)); + if (!IsAligned(ptr, ASAN_SHADOW_GRANULARITY)) { *(u8 *)MemToShadow(ptr) = - poison ? static_cast(ptr % SHADOW_GRANULARITY) : 0; - ptr |= SHADOW_GRANULARITY - 1; + poison ? static_cast(ptr % ASAN_SHADOW_GRANULARITY) : 0; + ptr |= ASAN_SHADOW_GRANULARITY - 1; ptr++; } - for (; ptr < end; ptr += SHADOW_GRANULARITY) + for (; ptr < end; ptr += ASAN_SHADOW_GRANULARITY) *(u8*)MemToShadow(ptr) = poison ? kAsanIntraObjectRedzone : 0; } @@ -181,12 +183,12 @@ uptr __asan_region_is_poisoned(uptr beg, uptr size) { if (!AddrIsInMem(end)) return end; CHECK_LT(beg, end); - uptr aligned_b = RoundUpTo(beg, SHADOW_GRANULARITY); - uptr aligned_e = RoundDownTo(end, SHADOW_GRANULARITY); + uptr aligned_b = RoundUpTo(beg, ASAN_SHADOW_GRANULARITY); + uptr aligned_e = RoundDownTo(end, ASAN_SHADOW_GRANULARITY); uptr shadow_beg = MemToShadow(aligned_b); uptr shadow_end = MemToShadow(aligned_e); // First check the first and the last application bytes, - // then check the SHADOW_GRANULARITY-aligned region by calling + // then check the ASAN_SHADOW_GRANULARITY-aligned region by calling // mem_is_zero on the corresponding shadow. if (!__asan::AddressIsPoisoned(beg) && !__asan::AddressIsPoisoned(end - 1) && (shadow_end <= shadow_beg || @@ -285,7 +287,7 @@ uptr __asan_load_cxx_array_cookie(uptr *p) { // assumes that left border of region to be poisoned is properly aligned. static void PoisonAlignedStackMemory(uptr addr, uptr size, bool do_poison) { if (size == 0) return; - uptr aligned_size = size & ~(SHADOW_GRANULARITY - 1); + uptr aligned_size = size & ~(ASAN_SHADOW_GRANULARITY - 1); PoisonShadow(addr, aligned_size, do_poison ? kAsanStackUseAfterScopeMagic : 0); if (size == aligned_size) @@ -310,6 +312,34 @@ void __asan_set_shadow_00(uptr addr, uptr size) { REAL(memset)((void *)addr, 0, size); } +void __asan_set_shadow_01(uptr addr, uptr size) { + REAL(memset)((void *)addr, 0x01, size); +} + +void __asan_set_shadow_02(uptr addr, uptr size) { + REAL(memset)((void *)addr, 0x02, size); +} + +void __asan_set_shadow_03(uptr addr, uptr size) { + REAL(memset)((void *)addr, 0x03, size); +} + +void __asan_set_shadow_04(uptr addr, uptr size) { + REAL(memset)((void *)addr, 0x04, size); +} + +void __asan_set_shadow_05(uptr addr, uptr size) { + REAL(memset)((void *)addr, 0x05, size); +} + +void __asan_set_shadow_06(uptr addr, uptr size) { + REAL(memset)((void *)addr, 0x06, size); +} + +void __asan_set_shadow_07(uptr addr, uptr size) { + REAL(memset)((void *)addr, 0x07, size); +} + void __asan_set_shadow_f1(uptr addr, uptr size) { REAL(memset)((void *)addr, 0xf1, size); } @@ -340,30 +370,77 @@ void __asan_unpoison_stack_memory(uptr addr, uptr size) { PoisonAlignedStackMemory(addr, size, false); } +static void FixUnalignedStorage(uptr storage_beg, uptr storage_end, + uptr &old_beg, uptr &old_end, uptr &new_beg, + uptr &new_end) { + constexpr uptr granularity = ASAN_SHADOW_GRANULARITY; + if (UNLIKELY(!AddrIsAlignedByGranularity(storage_end))) { + uptr end_down = RoundDownTo(storage_end, granularity); + // Ignore the last unaligned granule if the storage is followed by + // unpoisoned byte, because we can't poison the prefix anyway. Don't call + // AddressIsPoisoned at all if container changes does not affect the last + // granule at all. + if ((((old_end != new_end) && Max(old_end, new_end) > end_down) || + ((old_beg != new_beg) && Max(old_beg, new_beg) > end_down)) && + !AddressIsPoisoned(storage_end)) { + old_beg = Min(end_down, old_beg); + old_end = Min(end_down, old_end); + new_beg = Min(end_down, new_beg); + new_end = Min(end_down, new_end); + } + } + + // Handle misaligned begin and cut it off. + if (UNLIKELY(!AddrIsAlignedByGranularity(storage_beg))) { + uptr beg_up = RoundUpTo(storage_beg, granularity); + // The first unaligned granule needs special handling only if we had bytes + // there before and will have none after. + if ((new_beg == new_end || new_beg >= beg_up) && old_beg != old_end && + old_beg < beg_up) { + // Keep granule prefix outside of the storage unpoisoned. + uptr beg_down = RoundDownTo(storage_beg, granularity); + *(u8 *)MemToShadow(beg_down) = storage_beg - beg_down; + old_beg = Max(beg_up, old_beg); + old_end = Max(beg_up, old_end); + new_beg = Max(beg_up, new_beg); + new_end = Max(beg_up, new_end); + } + } +} + void __sanitizer_annotate_contiguous_container(const void *beg_p, const void *end_p, const void *old_mid_p, const void *new_mid_p) { - if (!flags()->detect_container_overflow) return; + if (!flags()->detect_container_overflow) + return; VPrintf(2, "contiguous_container: %p %p %p %p\n", beg_p, end_p, old_mid_p, new_mid_p); - uptr beg = reinterpret_cast(beg_p); - uptr end = reinterpret_cast(end_p); - uptr old_mid = reinterpret_cast(old_mid_p); - uptr new_mid = reinterpret_cast(new_mid_p); - uptr granularity = SHADOW_GRANULARITY; - if (!(beg <= old_mid && beg <= new_mid && old_mid <= end && new_mid <= end && - IsAligned(beg, granularity))) { + uptr storage_beg = reinterpret_cast(beg_p); + uptr storage_end = reinterpret_cast(end_p); + uptr old_end = reinterpret_cast(old_mid_p); + uptr new_end = reinterpret_cast(new_mid_p); + uptr old_beg = storage_beg; + uptr new_beg = storage_beg; + uptr granularity = ASAN_SHADOW_GRANULARITY; + if (!(storage_beg <= old_end && storage_beg <= new_end && + old_end <= storage_end && new_end <= storage_end)) { GET_STACK_TRACE_FATAL_HERE; - ReportBadParamsToAnnotateContiguousContainer(beg, end, old_mid, new_mid, - &stack); + ReportBadParamsToAnnotateContiguousContainer(storage_beg, storage_end, + old_end, new_end, &stack); } - CHECK_LE(end - beg, - FIRST_32_SECOND_64(1UL << 30, 1ULL << 40)); // Sanity check. + CHECK_LE(storage_end - storage_beg, + FIRST_32_SECOND_64(1UL << 30, 1ULL << 40)); // Sanity check. + + if (old_end == new_end) + return; // Nothing to do here. - uptr a = RoundDownTo(Min(old_mid, new_mid), granularity); - uptr c = RoundUpTo(Max(old_mid, new_mid), granularity); - uptr d1 = RoundDownTo(old_mid, granularity); + FixUnalignedStorage(storage_beg, storage_end, old_beg, old_end, new_beg, + new_end); + + uptr a = RoundDownTo(Min(old_end, new_end), granularity); + uptr c = RoundUpTo(Max(old_end, new_end), granularity); + uptr d1 = RoundDownTo(old_end, granularity); // uptr d2 = RoundUpTo(old_mid, granularity); // Currently we should be in this state: // [a, d1) is good, [d2, c) is bad, [d1, d2) is partially good. @@ -374,54 +451,171 @@ void __sanitizer_annotate_contiguous_container(const void *beg_p, // if (d1 != d2) // CHECK_EQ(*(u8*)MemToShadow(d1), old_mid - d1); if (a + granularity <= d1) - CHECK_EQ(*(u8*)MemToShadow(a), 0); + CHECK_EQ(*(u8 *)MemToShadow(a), 0); // if (d2 + granularity <= c && c <= end) // CHECK_EQ(*(u8 *)MemToShadow(c - granularity), // kAsanContiguousContainerOOBMagic); - uptr b1 = RoundDownTo(new_mid, granularity); - uptr b2 = RoundUpTo(new_mid, granularity); + uptr b1 = RoundDownTo(new_end, granularity); + uptr b2 = RoundUpTo(new_end, granularity); // New state: // [a, b1) is good, [b2, c) is bad, [b1, b2) is partially good. - PoisonShadow(a, b1 - a, 0); - PoisonShadow(b2, c - b2, kAsanContiguousContainerOOBMagic); + if (b1 > a) + PoisonShadow(a, b1 - a, 0); + else if (c > b2) + PoisonShadow(b2, c - b2, kAsanContiguousContainerOOBMagic); if (b1 != b2) { CHECK_EQ(b2 - b1, granularity); - *(u8*)MemToShadow(b1) = static_cast(new_mid - b1); + *(u8 *)MemToShadow(b1) = static_cast(new_end - b1); + } +} + +// Annotates a double ended contiguous memory area like std::deque's chunk. +// It allows detecting buggy accesses to allocated but not used begining +// or end items of such a container. +void __sanitizer_annotate_double_ended_contiguous_container( + const void *storage_beg_p, const void *storage_end_p, + const void *old_container_beg_p, const void *old_container_end_p, + const void *new_container_beg_p, const void *new_container_end_p) { + if (!flags()->detect_container_overflow) + return; + + VPrintf(2, "contiguous_container: %p %p %p %p %p %p\n", storage_beg_p, + storage_end_p, old_container_beg_p, old_container_end_p, + new_container_beg_p, new_container_end_p); + + uptr storage_beg = reinterpret_cast(storage_beg_p); + uptr storage_end = reinterpret_cast(storage_end_p); + uptr old_beg = reinterpret_cast(old_container_beg_p); + uptr old_end = reinterpret_cast(old_container_end_p); + uptr new_beg = reinterpret_cast(new_container_beg_p); + uptr new_end = reinterpret_cast(new_container_end_p); + + constexpr uptr granularity = ASAN_SHADOW_GRANULARITY; + + if (!(old_beg <= old_end && new_beg <= new_end) || + !(storage_beg <= new_beg && new_end <= storage_end) || + !(storage_beg <= old_beg && old_end <= storage_end)) { + GET_STACK_TRACE_FATAL_HERE; + ReportBadParamsToAnnotateDoubleEndedContiguousContainer( + storage_beg, storage_end, old_beg, old_end, new_beg, new_end, &stack); } + CHECK_LE(storage_end - storage_beg, + FIRST_32_SECOND_64(1UL << 30, 1ULL << 40)); // Sanity check. + + if ((old_beg == old_end && new_beg == new_end) || + (old_beg == new_beg && old_end == new_end)) + return; // Nothing to do here. + + FixUnalignedStorage(storage_beg, storage_end, old_beg, old_end, new_beg, + new_end); + + // Handle non-intersecting new/old containers separately have simpler + // intersecting case. + if (old_beg == old_end || new_beg == new_end || new_end <= old_beg || + old_end <= new_beg) { + if (old_beg != old_end) { + // Poisoning the old container. + uptr a = RoundDownTo(old_beg, granularity); + uptr b = RoundUpTo(old_end, granularity); + PoisonShadow(a, b - a, kAsanContiguousContainerOOBMagic); + } + + if (new_beg != new_end) { + // Unpoisoning the new container. + uptr a = RoundDownTo(new_beg, granularity); + uptr b = RoundDownTo(new_end, granularity); + PoisonShadow(a, b - a, 0); + if (!AddrIsAlignedByGranularity(new_end)) + *(u8 *)MemToShadow(b) = static_cast(new_end - b); + } + + return; + } + + // Intersection of old and new containers is not empty. + CHECK_LT(new_beg, old_end); + CHECK_GT(new_end, old_beg); + + if (new_beg < old_beg) { + // Round down because we can't poison prefixes. + uptr a = RoundDownTo(new_beg, granularity); + // Round down and ignore the [c, old_beg) as its state defined by unchanged + // [old_beg, old_end). + uptr c = RoundDownTo(old_beg, granularity); + PoisonShadow(a, c - a, 0); + } else if (new_beg > old_beg) { + // Round down and poison [a, old_beg) because it was unpoisoned only as a + // prefix. + uptr a = RoundDownTo(old_beg, granularity); + // Round down and ignore the [c, new_beg) as its state defined by unchanged + // [new_beg, old_end). + uptr c = RoundDownTo(new_beg, granularity); + + PoisonShadow(a, c - a, kAsanContiguousContainerOOBMagic); + } + + if (new_end > old_end) { + // Round down to poison the prefix. + uptr a = RoundDownTo(old_end, granularity); + // Round down and handle remainder below. + uptr c = RoundDownTo(new_end, granularity); + PoisonShadow(a, c - a, 0); + if (!AddrIsAlignedByGranularity(new_end)) + *(u8 *)MemToShadow(c) = static_cast(new_end - c); + } else if (new_end < old_end) { + // Round up and handle remained below. + uptr a2 = RoundUpTo(new_end, granularity); + // Round up to poison entire granule as we had nothing in [old_end, c2). + uptr c2 = RoundUpTo(old_end, granularity); + PoisonShadow(a2, c2 - a2, kAsanContiguousContainerOOBMagic); + + if (!AddrIsAlignedByGranularity(new_end)) { + uptr a = RoundDownTo(new_end, granularity); + *(u8 *)MemToShadow(a) = static_cast(new_end - a); + } + } +} + +static const void *FindBadAddress(uptr begin, uptr end, bool poisoned) { + CHECK_LE(begin, end); + constexpr uptr kMaxRangeToCheck = 32; + if (end - begin > kMaxRangeToCheck * 2) { + if (auto *bad = FindBadAddress(begin, begin + kMaxRangeToCheck, poisoned)) + return bad; + if (auto *bad = FindBadAddress(end - kMaxRangeToCheck, end, poisoned)) + return bad; + } + + for (uptr i = begin; i < end; ++i) + if (AddressIsPoisoned(i) != poisoned) + return reinterpret_cast(i); + return nullptr; } const void *__sanitizer_contiguous_container_find_bad_address( const void *beg_p, const void *mid_p, const void *end_p) { if (!flags()->detect_container_overflow) return nullptr; + uptr granularity = ASAN_SHADOW_GRANULARITY; uptr beg = reinterpret_cast(beg_p); uptr end = reinterpret_cast(end_p); uptr mid = reinterpret_cast(mid_p); CHECK_LE(beg, mid); CHECK_LE(mid, end); - // Check some bytes starting from beg, some bytes around mid, and some bytes - // ending with end. - uptr kMaxRangeToCheck = 32; - uptr r1_beg = beg; - uptr r1_end = Min(beg + kMaxRangeToCheck, mid); - uptr r2_beg = Max(beg, mid - kMaxRangeToCheck); - uptr r2_end = Min(end, mid + kMaxRangeToCheck); - uptr r3_beg = Max(end - kMaxRangeToCheck, mid); - uptr r3_end = end; - for (uptr i = r1_beg; i < r1_end; i++) - if (AddressIsPoisoned(i)) - return reinterpret_cast(i); - for (uptr i = r2_beg; i < mid; i++) - if (AddressIsPoisoned(i)) - return reinterpret_cast(i); - for (uptr i = mid; i < r2_end; i++) - if (!AddressIsPoisoned(i)) - return reinterpret_cast(i); - for (uptr i = r3_beg; i < r3_end; i++) - if (!AddressIsPoisoned(i)) - return reinterpret_cast(i); - return nullptr; + // If the byte after the storage is unpoisoned, everything in the granule + // before must stay unpoisoned. + uptr annotations_end = + (!AddrIsAlignedByGranularity(end) && !AddressIsPoisoned(end)) + ? RoundDownTo(end, granularity) + : end; + beg = Min(beg, annotations_end); + mid = Min(mid, annotations_end); + if (auto *bad = FindBadAddress(beg, mid, false)) + return bad; + if (auto *bad = FindBadAddress(mid, annotations_end, true)) + return bad; + return FindBadAddress(annotations_end, end, false); } int __sanitizer_verify_contiguous_container(const void *beg_p, @@ -431,6 +625,48 @@ int __sanitizer_verify_contiguous_container(const void *beg_p, end_p) == nullptr; } +const void *__sanitizer_double_ended_contiguous_container_find_bad_address( + const void *storage_beg_p, const void *container_beg_p, + const void *container_end_p, const void *storage_end_p) { + if (!flags()->detect_container_overflow) + return nullptr; + uptr granularity = ASAN_SHADOW_GRANULARITY; + uptr storage_beg = reinterpret_cast(storage_beg_p); + uptr storage_end = reinterpret_cast(storage_end_p); + uptr beg = reinterpret_cast(container_beg_p); + uptr end = reinterpret_cast(container_end_p); + + // The prefix of the firs granule of the container is unpoisoned. + if (beg != end) + beg = Max(storage_beg, RoundDownTo(beg, granularity)); + + // If the byte after the storage is unpoisoned, the prefix of the last granule + // is unpoisoned. + uptr annotations_end = (!AddrIsAlignedByGranularity(storage_end) && + !AddressIsPoisoned(storage_end)) + ? RoundDownTo(storage_end, granularity) + : storage_end; + storage_beg = Min(storage_beg, annotations_end); + beg = Min(beg, annotations_end); + end = Min(end, annotations_end); + + if (auto *bad = FindBadAddress(storage_beg, beg, true)) + return bad; + if (auto *bad = FindBadAddress(beg, end, false)) + return bad; + if (auto *bad = FindBadAddress(end, annotations_end, true)) + return bad; + return FindBadAddress(annotations_end, storage_end, false); +} + +int __sanitizer_verify_double_ended_contiguous_container( + const void *storage_beg_p, const void *container_beg_p, + const void *container_end_p, const void *storage_end_p) { + return __sanitizer_double_ended_contiguous_container_find_bad_address( + storage_beg_p, container_beg_p, container_end_p, storage_end_p) == + nullptr; +} + extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __asan_poison_intra_object_redzone(uptr ptr, uptr size) { AsanPoisonOrUnpoisonIntraObjectRedzone(ptr, size, true); diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_poisoning.h b/gnu/llvm/compiler-rt/lib/asan/asan_poisoning.h index 3d536f2d309..600bd011f30 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_poisoning.h +++ b/gnu/llvm/compiler-rt/lib/asan/asan_poisoning.h @@ -44,8 +44,8 @@ ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size, common_flags()->clear_shadow_mmap_threshold); #else uptr shadow_beg = MEM_TO_SHADOW(aligned_beg); - uptr shadow_end = MEM_TO_SHADOW( - aligned_beg + aligned_size - SHADOW_GRANULARITY) + 1; + uptr shadow_end = + MEM_TO_SHADOW(aligned_beg + aligned_size - ASAN_SHADOW_GRANULARITY) + 1; // FIXME: Page states are different on Windows, so using the same interface // for mapping shadow and zeroing out pages doesn't "just work", so we should // probably provide higher-level interface for these operations. @@ -78,11 +78,12 @@ ALWAYS_INLINE void FastPoisonShadowPartialRightRedzone( DCHECK(CanPoisonMemory()); bool poison_partial = flags()->poison_partial; u8 *shadow = (u8*)MEM_TO_SHADOW(aligned_addr); - for (uptr i = 0; i < redzone_size; i += SHADOW_GRANULARITY, shadow++) { - if (i + SHADOW_GRANULARITY <= size) { + for (uptr i = 0; i < redzone_size; i += ASAN_SHADOW_GRANULARITY, shadow++) { + if (i + ASAN_SHADOW_GRANULARITY <= size) { *shadow = 0; // fully addressable } else if (i >= size) { - *shadow = (SHADOW_GRANULARITY == 128) ? 0xff : value; // unaddressable + *shadow = + (ASAN_SHADOW_GRANULARITY == 128) ? 0xff : value; // unaddressable } else { // first size-i bytes are addressable *shadow = poison_partial ? static_cast(size - i) : 0; diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_posix.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_posix.cpp index 63ad735f8bb..765f4a26cd7 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_posix.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_posix.cpp @@ -14,22 +14,23 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_POSIX -#include "asan_internal.h" -#include "asan_interceptors.h" -#include "asan_mapping.h" -#include "asan_poisoning.h" -#include "asan_report.h" -#include "asan_stack.h" -#include "sanitizer_common/sanitizer_libc.h" -#include "sanitizer_common/sanitizer_posix.h" -#include "sanitizer_common/sanitizer_procmaps.h" - -#include -#include -#include -#include -#include -#include +# include +# include +# include +# include +# include +# include + +# include "asan_interceptors.h" +# include "asan_internal.h" +# include "asan_mapping.h" +# include "asan_poisoning.h" +# include "asan_report.h" +# include "asan_stack.h" +# include "lsan/lsan_common.h" +# include "sanitizer_common/sanitizer_libc.h" +# include "sanitizer_common/sanitizer_posix.h" +# include "sanitizer_common/sanitizer_procmaps.h" namespace __asan { @@ -131,7 +132,7 @@ void AsanTSDSet(void *tsd) { } void PlatformTSDDtor(void *tsd) { - AsanThreadContext *context = (AsanThreadContext*)tsd; + AsanThreadContext *context = (AsanThreadContext *)tsd; if (context->destructor_iterations > 1) { context->destructor_iterations--; CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); @@ -140,6 +141,18 @@ void PlatformTSDDtor(void *tsd) { AsanThread::TSDDtor(tsd); } #endif + +void InstallAtExitCheckLeaks() { + if (CAN_SANITIZE_LEAKS) { + if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) { + if (flags()->halt_on_error) + Atexit(__lsan::DoLeakCheck); + else + Atexit(__lsan::DoRecoverableLeakCheckVoid); + } + } +} + } // namespace __asan #endif // SANITIZER_POSIX diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_premap_shadow.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_premap_shadow.cpp index 666bb9b34bd..bed2f62a225 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_premap_shadow.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_premap_shadow.cpp @@ -26,7 +26,7 @@ namespace __asan { // Conservative upper limit. uptr PremapShadowSize() { uptr granularity = GetMmapGranularity(); - return RoundUpTo(GetMaxVirtualAddress() >> SHADOW_SCALE, granularity); + return RoundUpTo(GetMaxVirtualAddress() >> ASAN_SHADOW_SCALE, granularity); } // Returns an address aligned to 8 pages, such that one page on the left and diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_report.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_report.cpp index 03f1ed2b018..f2c04342e77 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_report.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_report.cpp @@ -11,17 +11,19 @@ // This file contains error reporting code. //===----------------------------------------------------------------------===// +#include "asan_report.h" + +#include "asan_descriptions.h" #include "asan_errors.h" #include "asan_flags.h" -#include "asan_descriptions.h" #include "asan_internal.h" #include "asan_mapping.h" -#include "asan_report.h" #include "asan_scariness_score.h" #include "asan_stack.h" #include "asan_thread.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flags.h" +#include "sanitizer_common/sanitizer_interface_internal.h" #include "sanitizer_common/sanitizer_report_decorator.h" #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_symbolizer.h" @@ -32,12 +34,12 @@ namespace __asan { static void (*error_report_callback)(const char*); static char *error_message_buffer = nullptr; static uptr error_message_buffer_pos = 0; -static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED); +static Mutex error_message_buf_mutex; static const unsigned kAsanBuggyPcPoolSize = 25; static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize]; void AppendToErrorMessageBuffer(const char *buffer) { - BlockingMutexLock l(&error_message_buf_mutex); + Lock l(&error_message_buf_mutex); if (!error_message_buffer) { error_message_buffer = (char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__); @@ -67,14 +69,14 @@ static void PrintZoneForPointer(uptr ptr, uptr zone_ptr, const char *zone_name) { if (zone_ptr) { if (zone_name) { - Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n", - ptr, zone_ptr, zone_name); + Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n", (void *)ptr, + (void *)zone_ptr, zone_name); } else { Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n", - ptr, zone_ptr); + (void *)ptr, (void *)zone_ptr); } } else { - Printf("malloc_zone_from_ptr(%p) = 0\n", ptr); + Printf("malloc_zone_from_ptr(%p) = 0\n", (void *)ptr); } } @@ -155,10 +157,10 @@ class ScopedInErrorReport { DumpProcessMap(); // Copy the message buffer so that we could start logging without holding a - // lock that gets aquired during printing. + // lock that gets acquired during printing. InternalMmapVector buffer_copy(kErrorMessageBufferSize); { - BlockingMutexLock l(&error_message_buf_mutex); + Lock l(&error_message_buf_mutex); internal_memcpy(buffer_copy.data(), error_message_buffer, kErrorMessageBufferSize); // Clear error_message_buffer so that if we find other errors @@ -352,6 +354,18 @@ void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, in_report.ReportError(error); } +void ReportBadParamsToAnnotateDoubleEndedContiguousContainer( + uptr storage_beg, uptr storage_end, uptr old_container_beg, + uptr old_container_end, uptr new_container_beg, uptr new_container_end, + BufferedStackTrace *stack) { + ScopedInErrorReport in_report; + ErrorBadParamsToAnnotateDoubleEndedContiguousContainer error( + GetCurrentTidOrInvalid(), stack, storage_beg, storage_end, + old_container_beg, old_container_end, new_container_beg, + new_container_end); + in_report.ReportError(error); +} + void ReportODRViolation(const __asan_global *g1, u32 stack_id1, const __asan_global *g2, u32 stack_id2) { ScopedInErrorReport in_report; @@ -435,9 +449,10 @@ static inline void CheckForInvalidPointerPair(void *p1, void *p2) { void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name, BufferedStackTrace *stack) { ScopedInErrorReport in_report; - Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n" - "This is an unrecoverable problem, exiting now.\n", - addr); + Printf( + "mz_realloc(%p) -- attempting to realloc unallocated memory.\n" + "This is an unrecoverable problem, exiting now.\n", + (void *)addr); PrintZoneForPointer(addr, zone_ptr, zone_name); stack->Print(); DescribeAddressIfHeap(addr); @@ -459,6 +474,10 @@ static bool SuppressErrorReport(uptr pc) { void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write, uptr access_size, u32 exp, bool fatal) { + if (__asan_test_only_reported_buggy_pointer) { + *__asan_test_only_reported_buggy_pointer = addr; + return; + } if (!fatal && SuppressErrorReport(pc)) return; ENABLE_FRAME_POINTER; @@ -490,7 +509,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, } void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) { - BlockingMutexLock l(&error_message_buf_mutex); + Lock l(&error_message_buf_mutex); error_report_callback = callback; } diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_report.h b/gnu/llvm/compiler-rt/lib/asan/asan_report.h index dcf60894ef3..248e30dd42b 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_report.h +++ b/gnu/llvm/compiler-rt/lib/asan/asan_report.h @@ -83,6 +83,10 @@ void ReportStringFunctionSizeOverflow(uptr offset, uptr size, void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, uptr old_mid, uptr new_mid, BufferedStackTrace *stack); +void ReportBadParamsToAnnotateDoubleEndedContiguousContainer( + uptr storage_beg, uptr storage_end, uptr old_container_beg, + uptr old_container_end, uptr new_container_beg, uptr new_container_end, + BufferedStackTrace *stack); void ReportODRViolation(const __asan_global *g1, u32 stack_id1, const __asan_global *g2, u32 stack_id2); diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_rtl.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_rtl.cpp index bfaa3bc2702..853083182b4 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_rtl.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_rtl.cpp @@ -27,6 +27,7 @@ #include "lsan/lsan_common.h" #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_flags.h" +#include "sanitizer_common/sanitizer_interface_internal.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_symbolizer.h" #include "ubsan/ubsan_init.h" @@ -44,14 +45,15 @@ static void AsanDie() { static atomic_uint32_t num_calls; if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { // Don't die twice - run a busy loop. - while (1) { } + while (1) { + internal_sched_yield(); + } } if (common_flags()->print_module_map >= 1) DumpProcessMap(); - if (flags()->sleep_before_dying) { - Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying); - SleepForSeconds(flags()->sleep_before_dying); - } + + WaitForDebugger(flags()->sleep_before_dying, "before dying"); + if (flags()->unmap_shadow_on_exit) { if (kMidMemBeg) { UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); @@ -71,6 +73,7 @@ static void CheckUnwind() { // -------------------------- Globals --------------------- {{{1 int asan_inited; bool asan_init_is_running; +bool replace_intrin_cached; #if !ASAN_FIXED_MAPPING uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; @@ -85,12 +88,8 @@ void ShowStatsAndAbort() { NOINLINE static void ReportGenericErrorWrapper(uptr addr, bool is_write, int size, int exp_arg, bool fatal) { - if (__asan_test_only_reported_buggy_pointer) { - *__asan_test_only_reported_buggy_pointer = addr; - } else { - GET_CALLER_PC_BP_SP; - ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, fatal); - } + GET_CALLER_PC_BP_SP; + ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, fatal); } // --------------- LowLevelAllocateCallbac ---------- {{{1 @@ -150,11 +149,11 @@ ASAN_REPORT_ERROR_N(store, true) #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); \ + uptr s = size <= ASAN_SHADOW_GRANULARITY ? *reinterpret_cast(sp) \ + : *reinterpret_cast(sp); \ if (UNLIKELY(s)) { \ - if (UNLIKELY(size >= SHADOW_GRANULARITY || \ - ((s8)((addr & (SHADOW_GRANULARITY - 1)) + size - 1)) >= \ + if (UNLIKELY(size >= ASAN_SHADOW_GRANULARITY || \ + ((s8)((addr & (ASAN_SHADOW_GRANULARITY - 1)) + size - 1)) >= \ (s8)s)) { \ ReportGenericErrorWrapper(addr, is_write, size, exp_arg, fatal); \ } \ @@ -188,7 +187,7 @@ ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16) extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_loadN(uptr addr, uptr size) { - if (__asan_region_is_poisoned(addr, size)) { + if ((addr = __asan_region_is_poisoned(addr, size))) { GET_CALLER_PC_BP_SP; ReportGenericError(pc, bp, sp, addr, false, size, 0, true); } @@ -197,7 +196,7 @@ void __asan_loadN(uptr addr, uptr size) { extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_exp_loadN(uptr addr, uptr size, u32 exp) { - if (__asan_region_is_poisoned(addr, size)) { + if ((addr = __asan_region_is_poisoned(addr, size))) { GET_CALLER_PC_BP_SP; ReportGenericError(pc, bp, sp, addr, false, size, exp, true); } @@ -206,7 +205,7 @@ void __asan_exp_loadN(uptr addr, uptr size, u32 exp) { extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_loadN_noabort(uptr addr, uptr size) { - if (__asan_region_is_poisoned(addr, size)) { + if ((addr = __asan_region_is_poisoned(addr, size))) { GET_CALLER_PC_BP_SP; ReportGenericError(pc, bp, sp, addr, false, size, 0, false); } @@ -215,7 +214,7 @@ void __asan_loadN_noabort(uptr addr, uptr size) { extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_storeN(uptr addr, uptr size) { - if (__asan_region_is_poisoned(addr, size)) { + if ((addr = __asan_region_is_poisoned(addr, size))) { GET_CALLER_PC_BP_SP; ReportGenericError(pc, bp, sp, addr, true, size, 0, true); } @@ -224,7 +223,7 @@ void __asan_storeN(uptr addr, uptr size) { extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_exp_storeN(uptr addr, uptr size, u32 exp) { - if (__asan_region_is_poisoned(addr, size)) { + if ((addr = __asan_region_is_poisoned(addr, size))) { GET_CALLER_PC_BP_SP; ReportGenericError(pc, bp, sp, addr, true, size, exp, true); } @@ -233,7 +232,7 @@ void __asan_exp_storeN(uptr addr, uptr size, u32 exp) { extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_storeN_noabort(uptr addr, uptr size) { - if (__asan_region_is_poisoned(addr, size)) { + if ((addr = __asan_region_is_poisoned(addr, size))) { GET_CALLER_PC_BP_SP; ReportGenericError(pc, bp, sp, addr, true, size, 0, false); } @@ -289,11 +288,18 @@ static NOINLINE void force_interface_symbols() { case 38: __asan_region_is_poisoned(0, 0); break; case 39: __asan_describe_address(0); break; case 40: __asan_set_shadow_00(0, 0); break; - case 41: __asan_set_shadow_f1(0, 0); break; - case 42: __asan_set_shadow_f2(0, 0); break; - case 43: __asan_set_shadow_f3(0, 0); break; - case 44: __asan_set_shadow_f5(0, 0); break; - case 45: __asan_set_shadow_f8(0, 0); break; + case 41: __asan_set_shadow_01(0, 0); break; + case 42: __asan_set_shadow_02(0, 0); break; + case 43: __asan_set_shadow_03(0, 0); break; + case 44: __asan_set_shadow_04(0, 0); break; + case 45: __asan_set_shadow_05(0, 0); break; + case 46: __asan_set_shadow_06(0, 0); break; + case 47: __asan_set_shadow_07(0, 0); break; + case 48: __asan_set_shadow_f1(0, 0); break; + case 49: __asan_set_shadow_f2(0, 0); break; + case 50: __asan_set_shadow_f3(0, 0); break; + case 51: __asan_set_shadow_f5(0, 0); break; + case 52: __asan_set_shadow_f8(0, 0); break; } // clang-format on } @@ -313,7 +319,7 @@ static void InitializeHighMemEnd() { kHighMemEnd = GetMaxUserVirtualAddress(); // Increase kHighMemEnd to make sure it's properly // aligned together with kHighMemBeg: - kHighMemEnd |= (GetMmapGranularity() << SHADOW_SCALE) - 1; + kHighMemEnd |= (GetMmapGranularity() << ASAN_SHADOW_SCALE) - 1; #endif // !ASAN_FIXED_MAPPING CHECK_EQ((kHighMemBeg % GetMmapGranularity()), 0); } @@ -365,29 +371,16 @@ void PrintAddressSpaceLayout() { Printf("malloc_context_size=%zu\n", (uptr)common_flags()->malloc_context_size); - Printf("SHADOW_SCALE: %d\n", (int)SHADOW_SCALE); - Printf("SHADOW_GRANULARITY: %d\n", (int)SHADOW_GRANULARITY); - Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)SHADOW_OFFSET); - CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7); + Printf("SHADOW_SCALE: %d\n", (int)ASAN_SHADOW_SCALE); + Printf("SHADOW_GRANULARITY: %d\n", (int)ASAN_SHADOW_GRANULARITY); + Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)ASAN_SHADOW_OFFSET); + CHECK(ASAN_SHADOW_SCALE >= 3 && ASAN_SHADOW_SCALE <= 7); if (kMidMemBeg) CHECK(kMidShadowBeg > kLowShadowEnd && kMidMemBeg > kMidShadowEnd && kHighShadowBeg > kMidMemEnd); } -#if defined(__thumb__) && defined(__linux__) -#define START_BACKGROUND_THREAD_IN_ASAN_INTERNAL -#endif - -#ifndef START_BACKGROUND_THREAD_IN_ASAN_INTERNAL -static bool UNUSED __local_asan_dyninit = [] { - MaybeStartBackgroudThread(); - SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback); - - return false; -}(); -#endif - static void AsanInitInternal() { if (LIKELY(asan_inited)) return; SanitizerToolName = "AddressSanitizer"; @@ -400,6 +393,8 @@ static void AsanInitInternal() { // initialization steps look at flags(). InitializeFlags(); + WaitForDebugger(flags()->sleep_before_init, "before init"); + // Stop performing init at this point if we are being loaded via // dlopen() and the platform supports it. if (SANITIZER_SUPPORTS_INIT_FOR_DLOPEN && UNLIKELY(HandleDlopenInit())) { @@ -434,11 +429,8 @@ static void AsanInitInternal() { __sanitizer::InitializePlatformEarly(); - // Re-exec ourselves if we need to set additional env or command line args. - MaybeReexec(); - // Setup internal allocator callback. - SetLowLevelAllocateMinAlignment(SHADOW_GRANULARITY); + SetLowLevelAllocateMinAlignment(ASAN_SHADOW_GRANULARITY); SetLowLevelAllocateCallback(OnLowLevelAllocate); InitializeAsanInterceptors(); @@ -462,13 +454,12 @@ static void AsanInitInternal() { allocator_options.SetFrom(flags(), common_flags()); InitializeAllocator(allocator_options); -#ifdef START_BACKGROUND_THREAD_IN_ASAN_INTERNAL - MaybeStartBackgroudThread(); - SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback); -#endif + if (SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL) + MaybeStartBackgroudThread(); // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited // should be set to 1 prior to initializing the threads. + replace_intrin_cached = flags()->replace_intrin; asan_inited = 1; asan_init_is_running = false; @@ -493,12 +484,7 @@ static void AsanInitInternal() { if (CAN_SANITIZE_LEAKS) { __lsan::InitCommonLsan(); - if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) { - if (flags()->halt_on_error) - Atexit(__lsan::DoLeakCheck); - else - Atexit(__lsan::DoRecoverableLeakCheckVoid); - } + InstallAtExitCheckLeaks(); } #if CAN_SANITIZE_UB @@ -518,10 +504,7 @@ static void AsanInitInternal() { VReport(1, "AddressSanitizer Init done\n"); - if (flags()->sleep_after_init) { - Report("Sleeping for %d second(s)\n", flags()->sleep_after_init); - SleepForSeconds(flags()->sleep_after_init); - } + WaitForDebugger(flags()->sleep_after_init, "after init"); } // Initialize as requested from some part of ASan runtime library (interceptors, @@ -557,10 +540,11 @@ void UnpoisonStack(uptr bottom, uptr top, const char *type) { "False positive error reports may follow\n" "For details see " "https://github.com/google/sanitizers/issues/189\n", - type, top, bottom, top - bottom, top - bottom); + type, (void *)top, (void *)bottom, (void *)(top - bottom), + top - bottom); return; } - PoisonShadow(bottom, RoundUpTo(top - bottom, SHADOW_GRANULARITY), 0); + PoisonShadow(bottom, RoundUpTo(top - bottom, ASAN_SHADOW_GRANULARITY), 0); } static void UnpoisonDefaultStack() { diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_rtl_static.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_rtl_static.cpp new file mode 100644 index 00000000000..a6f812bb891 --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/asan/asan_rtl_static.cpp @@ -0,0 +1,36 @@ +//===-- asan_static_rtl.cpp -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +// Main file of the ASan run-time library. +//===----------------------------------------------------------------------===// + +// This file is empty for now. Main reason to have it is workaround for Windows +// build, which complains because no files are part of the asan_static lib. + +#include "sanitizer_common/sanitizer_common.h" + +#define REPORT_FUNCTION(Name) \ + extern "C" SANITIZER_WEAK_ATTRIBUTE void Name(__asan::uptr addr); \ + extern "C" void Name##_asm(uptr addr) { Name(addr); } + +namespace __asan { + +REPORT_FUNCTION(__asan_report_load1) +REPORT_FUNCTION(__asan_report_load2) +REPORT_FUNCTION(__asan_report_load4) +REPORT_FUNCTION(__asan_report_load8) +REPORT_FUNCTION(__asan_report_load16) +REPORT_FUNCTION(__asan_report_store1) +REPORT_FUNCTION(__asan_report_store2) +REPORT_FUNCTION(__asan_report_store4) +REPORT_FUNCTION(__asan_report_store8) +REPORT_FUNCTION(__asan_report_store16) + +} // namespace __asan diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_rtl_x86_64.S b/gnu/llvm/compiler-rt/lib/asan/asan_rtl_x86_64.S new file mode 100644 index 00000000000..d93b5ed2a7f --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/asan/asan_rtl_x86_64.S @@ -0,0 +1,146 @@ +#include "asan_mapping.h" +#include "sanitizer_common/sanitizer_asm.h" + +#if defined(__x86_64__) +#include "sanitizer_common/sanitizer_platform.h" + +.file "asan_rtl_x86_64.S" + +#define NAME(n, reg, op, s, i) n##_##op##_##i##_##s##_##reg + +#define FNAME(reg, op, s, i) NAME(__asan_check, reg, op, s, i) +#define RLABEL(reg, op, s, i) NAME(.return, reg, op, s, i) +#define CLABEL(reg, op, s, i) NAME(.check, reg, op, s, i) +#define FLABEL(reg, op, s, i) NAME(.fail, reg, op, s, i) + +#define BEGINF(reg, op, s, i) \ +.section .text.FNAME(reg, op, s, i),"ax",@progbits ;\ +.globl FNAME(reg, op, s, i) ;\ +.hidden FNAME(reg, op, s, i) ;\ +ASM_TYPE_FUNCTION(FNAME(reg, op, s, i)) ;\ +.cfi_startproc ;\ +FNAME(reg, op, s, i): ;\ + +#define ENDF .cfi_endproc ;\ + +// Access check functions for 1,2 and 4 byte types, which require extra checks. +#define ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, s) \ + mov %##reg,%r10 ;\ + shr $0x3,%r10 ;\ + movsbl ASAN_SHADOW_OFFSET_CONST(%r10),%r10d ;\ + test %r10d,%r10d ;\ + jne CLABEL(reg, op, s, add) ;\ +RLABEL(reg, op, s, add): ;\ + retq ;\ + +#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, i) \ +CLABEL(reg, op, 1, i): ;\ + push %rcx ;\ + mov %##reg,%rcx ;\ + and $0x7,%ecx ;\ + cmp %r10d,%ecx ;\ + pop %rcx ;\ + jl RLABEL(reg, op, 1, i);\ + mov %##reg,%rdi ;\ + jmp __asan_report_##op##1_asm ;\ + +#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, i) \ +CLABEL(reg, op, 2, i): ;\ + push %rcx ;\ + mov %##reg,%rcx ;\ + and $0x7,%ecx ;\ + add $0x1,%ecx ;\ + cmp %r10d,%ecx ;\ + pop %rcx ;\ + jl RLABEL(reg, op, 2, i);\ + mov %##reg,%rdi ;\ + jmp __asan_report_##op##2_asm ;\ + +#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, i) \ +CLABEL(reg, op, 4, i): ;\ + push %rcx ;\ + mov %##reg,%rcx ;\ + and $0x7,%ecx ;\ + add $0x3,%ecx ;\ + cmp %r10d,%ecx ;\ + pop %rcx ;\ + jl RLABEL(reg, op, 4, i);\ + mov %##reg,%rdi ;\ + jmp __asan_report_##op##4_asm ;\ + +#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, op) \ +BEGINF(reg, op, 1, add) ;\ + ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 1) ;\ + ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, add) ;\ +ENDF + +#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, op) \ +BEGINF(reg, op, 2, add) ;\ + ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 2) ;\ + ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, add) ;\ +ENDF + +#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, op) \ +BEGINF(reg, op, 4, add) ;\ + ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 4) ;\ + ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, add) ;\ +ENDF + +// Access check functions for 8 and 16 byte types: no extra checks required. +#define ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, s, c) \ + mov %##reg,%r10 ;\ + shr $0x3,%r10 ;\ + ##c $0x0,ASAN_SHADOW_OFFSET_CONST(%r10) ;\ + jne FLABEL(reg, op, s, add) ;\ + retq ;\ + +#define ASAN_MEMORY_ACCESS_FAIL(reg, op, s, i) \ +FLABEL(reg, op, s, i): ;\ + mov %##reg,%rdi ;\ + jmp __asan_report_##op##s##_asm;\ + +#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, op) \ +BEGINF(reg, op, 8, add) ;\ + ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 8, cmpb) ;\ + ASAN_MEMORY_ACCESS_FAIL(reg, op, 8, add) ;\ +ENDF + +#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, op) \ +BEGINF(reg, op, 16, add) ;\ + ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 16, cmpw) ;\ + ASAN_MEMORY_ACCESS_FAIL(reg, op, 16, add) ;\ +ENDF + +#define ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \ +ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, load) \ +ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, store) \ +ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, load) \ +ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, store) \ +ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, load) \ +ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, store) \ +ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, load) \ +ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, store) \ +ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, load) \ +ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, store) \ + + +// Instantiate all but R10 and R11 callbacks. We are using PLTSafe class with +// the intrinsic, which guarantees that the code generation will never emit +// R10 or R11 callback. +ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX) +ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX) +ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX) +ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX) +ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI) +ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI) +ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP) +ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8) +ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9) +ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12) +ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13) +ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14) +ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15) + +#endif + +NO_EXEC_STACK_DIRECTIVE diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_shadow_setup.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_shadow_setup.cpp index 6e6260d3413..fc6de39622b 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_shadow_setup.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_shadow_setup.cpp @@ -33,7 +33,7 @@ static void ProtectGap(uptr addr, uptr size) { "protect_shadow_gap=0:" " not protecting shadow gap, allocating gap's shadow\n" "|| `[%p, %p]` || ShadowGap's shadow ||\n", - GapShadowBeg, GapShadowEnd); + (void*)GapShadowBeg, (void*)GapShadowEnd); ReserveShadowMemoryRange(GapShadowBeg, GapShadowEnd, "unprotected gap shadow"); return; @@ -113,7 +113,7 @@ void InitializeShadowMemory() { "Shadow memory range interleaves with an existing memory mapping. " "ASan cannot proceed correctly. ABORTING.\n"); Report("ASan shadow was supposed to be located in the [%p-%p] range.\n", - shadow_start, kHighShadowEnd); + (void*)shadow_start, (void*)kHighShadowEnd); MaybeReportLinuxPIEBug(); DumpProcessMap(); Die(); diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_stats.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_stats.cpp index 00ded8f5ef5..9a715ea76fe 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_stats.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_stats.cpp @@ -62,11 +62,11 @@ void AsanStats::MergeFrom(const AsanStats *stats) { dst_ptr[i] += src_ptr[i]; } -static BlockingMutex print_lock(LINKER_INITIALIZED); +static Mutex print_lock; static AsanStats unknown_thread_stats(LINKER_INITIALIZED); static AsanStats dead_threads_stats(LINKER_INITIALIZED); -static BlockingMutex dead_threads_stats_lock(LINKER_INITIALIZED); +static Mutex dead_threads_stats_lock; // Required for malloc_zone_statistics() on OS X. This can't be stored in // per-thread AsanStats. static uptr max_malloced_memory; @@ -87,7 +87,7 @@ static void GetAccumulatedStats(AsanStats *stats) { } stats->MergeFrom(&unknown_thread_stats); { - BlockingMutexLock lock(&dead_threads_stats_lock); + Lock lock(&dead_threads_stats_lock); stats->MergeFrom(&dead_threads_stats); } // This is not very accurate: we may miss allocation peaks that happen @@ -99,7 +99,7 @@ static void GetAccumulatedStats(AsanStats *stats) { } void FlushToDeadThreadStats(AsanStats *stats) { - BlockingMutexLock lock(&dead_threads_stats_lock); + Lock lock(&dead_threads_stats_lock); dead_threads_stats.MergeFrom(stats); stats->Clear(); } @@ -122,11 +122,11 @@ static void PrintAccumulatedStats() { AsanStats stats; GetAccumulatedStats(&stats); // Use lock to keep reports from mixing up. - BlockingMutexLock lock(&print_lock); + Lock lock(&print_lock); stats.Print(); - StackDepotStats *stack_depot_stats = StackDepotGetStats(); + StackDepotStats stack_depot_stats = StackDepotGetStats(); Printf("Stats: StackDepot: %zd ids; %zdM allocated\n", - stack_depot_stats->n_uniq_ids, stack_depot_stats->allocated >> 20); + stack_depot_stats.n_uniq_ids, stack_depot_stats.allocated >> 20); PrintInternalAllocatorStats(); } diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_thread.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_thread.cpp index 35d4467e7b5..003cd2b9eee 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_thread.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_thread.cpp @@ -43,11 +43,11 @@ void AsanThreadContext::OnFinished() { static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)]; static ThreadRegistry *asan_thread_registry; -static BlockingMutex mu_for_thread_context(LINKER_INITIALIZED); +static Mutex mu_for_thread_context; static LowLevelAllocator allocator_for_thread_context; static ThreadContextBase *GetAsanThreadContext(u32 tid) { - BlockingMutexLock lock(&mu_for_thread_context); + Lock lock(&mu_for_thread_context); return new(allocator_for_thread_context) AsanThreadContext(tid); } @@ -83,8 +83,7 @@ AsanThread *AsanThread::Create(thread_callback_t start_routine, void *arg, thread->start_routine_ = start_routine; thread->arg_ = arg; AsanThreadContext::CreateThreadContextArgs args = {thread, stack}; - asanThreadRegistry().CreateThread(*reinterpret_cast(thread), detached, - parent_tid, &args); + asanThreadRegistry().CreateThread(0, detached, parent_tid, &args); return thread; } @@ -254,7 +253,7 @@ void AsanThread::Init(const InitOptions *options) { int local = 0; VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(), (void *)stack_bottom_, (void *)stack_top_, stack_top_ - stack_bottom_, - &local); + (void *)&local); } // Fuchsia doesn't use ThreadStart. @@ -306,7 +305,7 @@ void AsanThread::SetThreadStackAndTls(const InitOptions *options) { uptr stack_size = 0; GetThreadStackAndTls(tid() == kMainTid, &stack_bottom_, &stack_size, &tls_begin_, &tls_size); - stack_top_ = RoundDownTo(stack_bottom_ + stack_size, SHADOW_GRANULARITY); + stack_top_ = RoundDownTo(stack_bottom_ + stack_size, ASAN_SHADOW_GRANULARITY); tls_end_ = tls_begin_ + tls_size; dtls_ = DTLS_Get(); @@ -322,11 +321,9 @@ void AsanThread::ClearShadowForThreadStackAndTLS() { if (stack_top_ != stack_bottom_) PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); if (tls_begin_ != tls_end_) { - uptr tls_begin_aligned = RoundDownTo(tls_begin_, SHADOW_GRANULARITY); - uptr tls_end_aligned = RoundUpTo(tls_end_, SHADOW_GRANULARITY); - FastPoisonShadowPartialRightRedzone(tls_begin_aligned, - tls_end_ - tls_begin_aligned, - tls_end_aligned - tls_end_, 0); + uptr tls_begin_aligned = RoundDownTo(tls_begin_, ASAN_SHADOW_GRANULARITY); + uptr tls_end_aligned = RoundUpTo(tls_end_, ASAN_SHADOW_GRANULARITY); + FastPoisonShadow(tls_begin_aligned, tls_end_aligned - tls_begin_aligned, 0); } } @@ -347,27 +344,27 @@ bool AsanThread::GetStackFrameAccessByAddr(uptr addr, return true; } uptr aligned_addr = RoundDownTo(addr, SANITIZER_WORDSIZE / 8); // align addr. - uptr mem_ptr = RoundDownTo(aligned_addr, SHADOW_GRANULARITY); + uptr mem_ptr = RoundDownTo(aligned_addr, ASAN_SHADOW_GRANULARITY); u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr); u8 *shadow_bottom = (u8*)MemToShadow(bottom); while (shadow_ptr >= shadow_bottom && *shadow_ptr != kAsanStackLeftRedzoneMagic) { shadow_ptr--; - mem_ptr -= SHADOW_GRANULARITY; + mem_ptr -= ASAN_SHADOW_GRANULARITY; } while (shadow_ptr >= shadow_bottom && *shadow_ptr == kAsanStackLeftRedzoneMagic) { shadow_ptr--; - mem_ptr -= SHADOW_GRANULARITY; + mem_ptr -= ASAN_SHADOW_GRANULARITY; } if (shadow_ptr < shadow_bottom) { return false; } - uptr* ptr = (uptr*)(mem_ptr + SHADOW_GRANULARITY); + uptr *ptr = (uptr *)(mem_ptr + ASAN_SHADOW_GRANULARITY); CHECK(ptr[0] == kCurrentStackFrameMagic); access->offset = addr - (uptr)ptr; access->frame_pc = ptr[2]; @@ -443,7 +440,7 @@ AsanThread *GetCurrentThread() { void SetCurrentThread(AsanThread *t) { CHECK(t->context()); - VReport(2, "SetCurrentThread: %p for thread %p\n", t->context(), + VReport(2, "SetCurrentThread: %p for thread %p\n", (void *)t->context(), (void *)GetThreadSelf()); // Make sure we do not reset the current AsanThread. CHECK_EQ(0, AsanTSDGet()); @@ -481,6 +478,17 @@ __asan::AsanThread *GetAsanThreadByOsIDLocked(tid_t os_id) { // --- Implementation of LSan-specific functions --- {{{1 namespace __lsan { +void LockThreadRegistry() { __asan::asanThreadRegistry().Lock(); } + +void UnlockThreadRegistry() { __asan::asanThreadRegistry().Unlock(); } + +static ThreadRegistry *GetAsanThreadRegistryLocked() { + __asan::asanThreadRegistry().CheckLocked(); + return &__asan::asanThreadRegistry(); +} + +void EnsureMainThreadIDIsCorrect() { __asan::EnsureMainThreadIDIsCorrect(); } + bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end, uptr *tls_begin, uptr *tls_end, uptr *cache_begin, uptr *cache_end, DTLS **dtls) { @@ -499,33 +507,76 @@ bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end, void GetAllThreadAllocatorCachesLocked(InternalMmapVector *caches) {} -void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback, - void *arg) { +void GetThreadExtraStackRangesLocked(tid_t os_id, + InternalMmapVector *ranges) { __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id); if (!t) return; __asan::FakeStack *fake_stack = t->get_fake_stack(); if (!fake_stack) return; - fake_stack->ForEachFakeFrame(callback, arg); + + fake_stack->ForEachFakeFrame( + [](uptr begin, uptr end, void *arg) { + reinterpret_cast *>(arg)->push_back( + {begin, end}); + }, + ranges); } -void LockThreadRegistry() { - __asan::asanThreadRegistry().Lock(); +void GetThreadExtraStackRangesLocked(InternalMmapVector *ranges) { + GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked( + [](ThreadContextBase *tctx, void *arg) { + GetThreadExtraStackRangesLocked( + tctx->os_id, reinterpret_cast *>(arg)); + }, + ranges); } -void UnlockThreadRegistry() { - __asan::asanThreadRegistry().Unlock(); +void GetAdditionalThreadContextPtrsLocked(InternalMmapVector *ptrs) { + GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked( + [](ThreadContextBase *tctx, void *ptrs) { + // Look for the arg pointer of threads that have been created or are + // running. This is necessary to prevent false positive leaks due to the + // AsanThread holding the only live reference to a heap object. This + // can happen because the `pthread_create()` interceptor doesn't wait + // for the child thread to start before returning and thus loosing the + // the only live reference to the heap object on the stack. + + __asan::AsanThreadContext *atctx = + static_cast<__asan::AsanThreadContext *>(tctx); + + // Note ThreadStatusRunning is required because there is a small window + // where the thread status switches to `ThreadStatusRunning` but the + // `arg` pointer still isn't on the stack yet. + if (atctx->status != ThreadStatusCreated && + atctx->status != ThreadStatusRunning) + return; + + uptr thread_arg = reinterpret_cast(atctx->thread->get_arg()); + if (!thread_arg) + return; + + auto ptrsVec = reinterpret_cast *>(ptrs); + ptrsVec->push_back(thread_arg); + }, + ptrs); } -ThreadRegistry *GetThreadRegistryLocked() { - __asan::asanThreadRegistry().CheckLocked(); - return &__asan::asanThreadRegistry(); +void GetRunningThreadsLocked(InternalMmapVector *threads) { + GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked( + [](ThreadContextBase *tctx, void *threads) { + if (tctx->status == ThreadStatusRunning) + reinterpret_cast *>(threads)->push_back( + tctx->os_id); + }, + threads); } -void EnsureMainThreadIDIsCorrect() { - __asan::EnsureMainThreadIDIsCorrect(); +void FinishThreadLocked(u32 tid) { + GetAsanThreadRegistryLocked()->FinishThread(tid); } + } // namespace __lsan // ---------------------- Interface ---------------- {{{1 diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_win.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_win.cpp index 1577c83cf99..7dbd7ab98a1 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_win.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_win.cpp @@ -1,4 +1,5 @@ -//===-- asan_win.cpp ------------------------------------------------------===// +//===-- asan_win.cpp +//------------------------------------------------------===//> // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -13,21 +14,20 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_WINDOWS -#define WIN32_LEAN_AND_MEAN -#include - -#include - -#include "asan_interceptors.h" -#include "asan_internal.h" -#include "asan_mapping.h" -#include "asan_report.h" -#include "asan_stack.h" -#include "asan_thread.h" -#include "sanitizer_common/sanitizer_libc.h" -#include "sanitizer_common/sanitizer_mutex.h" -#include "sanitizer_common/sanitizer_win.h" -#include "sanitizer_common/sanitizer_win_defs.h" +# define WIN32_LEAN_AND_MEAN +# include +# include + +# include "asan_interceptors.h" +# include "asan_internal.h" +# include "asan_mapping.h" +# include "asan_report.h" +# include "asan_stack.h" +# include "asan_thread.h" +# include "sanitizer_common/sanitizer_libc.h" +# include "sanitizer_common/sanitizer_mutex.h" +# include "sanitizer_common/sanitizer_win.h" +# include "sanitizer_common/sanitizer_win_defs.h" using namespace __asan; @@ -49,8 +49,8 @@ uptr __asan_get_shadow_memory_dynamic_address() { static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler; static LPTOP_LEVEL_EXCEPTION_FILTER user_seh_handler; -extern "C" SANITIZER_INTERFACE_ATTRIBUTE -long __asan_unhandled_exception_filter(EXCEPTION_POINTERS *info) { +extern "C" SANITIZER_INTERFACE_ATTRIBUTE long __asan_unhandled_exception_filter( + EXCEPTION_POINTERS *info) { EXCEPTION_RECORD *exception_record = info->ExceptionRecord; CONTEXT *context = info->ContextRecord; @@ -187,6 +187,8 @@ void InitializePlatformInterceptors() { } } +void InstallAtExitCheckLeaks() {} + void AsanApplyToGlobals(globals_op_fptr op, const void *needle) { UNIMPLEMENTED(); } @@ -253,7 +255,7 @@ void *AsanDoesNotSupportStaticLinkage() { } uptr FindDynamicShadowStart() { - return MapDynamicShadow(MemToShadowSize(kHighMemEnd), SHADOW_SCALE, + return MapDynamicShadow(MemToShadowSize(kHighMemEnd), ASAN_SHADOW_SCALE, /*min_shadow_base_alignment*/ 0, kHighMemEnd); } @@ -261,10 +263,6 @@ void AsanCheckDynamicRTPrereqs() {} void AsanCheckIncompatibleRT() {} -void ReadContextStack(void *context, uptr *stack, uptr *ssize) { - UNIMPLEMENTED(); -} - void AsanOnDeadlySignal(int, void *siginfo, void *context) { UNIMPLEMENTED(); } bool PlatformUnpoisonStacks() { return false; } diff --git a/gnu/llvm/compiler-rt/lib/asan/asan_win_dll_thunk.cpp b/gnu/llvm/compiler-rt/lib/asan/asan_win_dll_thunk.cpp index a5671cc9dff..e3a90f18ed8 100644 --- a/gnu/llvm/compiler-rt/lib/asan/asan_win_dll_thunk.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/asan_win_dll_thunk.cpp @@ -56,6 +56,13 @@ INTERCEPT_WRAP_W_W(_expand_dbg) // TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cpp) +# if defined(_MSC_VER) && !defined(__clang__) +// Disable warnings such as: 'void memchr(void)': incorrect number of arguments +// for intrinsic function, expected '3' arguments. +# pragma warning(push) +# pragma warning(disable : 4392) +# endif + INTERCEPT_LIBRARY_FUNCTION(atoi); INTERCEPT_LIBRARY_FUNCTION(atol); INTERCEPT_LIBRARY_FUNCTION(frexp); @@ -87,6 +94,10 @@ INTERCEPT_LIBRARY_FUNCTION(strtol); INTERCEPT_LIBRARY_FUNCTION(wcslen); INTERCEPT_LIBRARY_FUNCTION(wcsnlen); +# if defined(_MSC_VER) && !defined(__clang__) +# pragma warning(pop) +# endif + #ifdef _WIN64 INTERCEPT_LIBRARY_FUNCTION(__C_specific_handler); #else diff --git a/gnu/llvm/compiler-rt/lib/asan/scripts/asan_device_setup b/gnu/llvm/compiler-rt/lib/asan/scripts/asan_device_setup index 95f9d35f51e..494867917fd 100755 --- a/gnu/llvm/compiler-rt/lib/asan/scripts/asan_device_setup +++ b/gnu/llvm/compiler-rt/lib/asan/scripts/asan_device_setup @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash #===- lib/asan/scripts/asan_device_setup -----------------------------------===# # # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. diff --git a/gnu/llvm/compiler-rt/lib/asan/scripts/asan_symbolize.py b/gnu/llvm/compiler-rt/lib/asan/scripts/asan_symbolize.py index ab04b1c67e5..4d5312858fd 100755 --- a/gnu/llvm/compiler-rt/lib/asan/scripts/asan_symbolize.py +++ b/gnu/llvm/compiler-rt/lib/asan/scripts/asan_symbolize.py @@ -50,7 +50,7 @@ def fix_filename(file_name): def is_valid_arch(s): return s in ["i386", "x86_64", "x86_64h", "arm", "armv6", "armv7", "armv7s", "armv7k", "arm64", "powerpc64", "powerpc64le", "s390x", "s390", - "riscv64"] + "riscv64", "loongarch64"] def guess_arch(addr): # Guess which arch we're running. 10 = len('0x') + 8 hex digits. diff --git a/gnu/llvm/compiler-rt/lib/asan/tests/CMakeLists.txt b/gnu/llvm/compiler-rt/lib/asan/tests/CMakeLists.txt index d7caf4c861b..a0c6d2910d6 100644 --- a/gnu/llvm/compiler-rt/lib/asan/tests/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/lib/asan/tests/CMakeLists.txt @@ -23,7 +23,7 @@ set(ASAN_UNITTEST_HEADERS set(ASAN_UNITTEST_COMMON_CFLAGS ${COMPILER_RT_UNITTEST_CFLAGS} ${COMPILER_RT_GTEST_CFLAGS} - ${COMPILER_RT_ASAN_SHADOW_SCALE_LLVM_FLAG} + ${SANITIZER_TEST_CXX_CFLAGS} -I${COMPILER_RT_SOURCE_DIR}/include -I${COMPILER_RT_SOURCE_DIR}/lib -I${COMPILER_RT_SOURCE_DIR}/lib/asan @@ -37,7 +37,9 @@ append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros ASAN_U # This will ensure the target linker is used # during cross compilation set(ASAN_UNITTEST_COMMON_LINK_FLAGS - ${COMPILER_RT_UNITTEST_LINK_FLAGS}) + ${COMPILER_RT_UNITTEST_LINK_FLAGS} + ${COMPILER_RT_UNWINDER_LINK_LIBS} + ${SANITIZER_TEST_CXX_LIBRARIES}) # -gline-tables-only must be enough for ASan, so use it if possible. if(COMPILER_RT_TEST_COMPILER_ID MATCHES "Clang") @@ -52,7 +54,6 @@ list(APPEND ASAN_UNITTEST_COMMON_LINK_FLAGS -g) # Use -D instead of definitions to please custom compile command. list(APPEND ASAN_UNITTEST_COMMON_CFLAGS - ${COMPILER_RT_ASAN_SHADOW_SCALE_FLAG} -DASAN_HAS_IGNORELIST=1 -DASAN_HAS_EXCEPTIONS=1 -DASAN_UAR=0 @@ -163,22 +164,32 @@ set(ASAN_BENCHMARKS_SOURCES function(add_asan_tests arch test_runtime) cmake_parse_arguments(TEST "" "KIND" "CFLAGS" ${ARGN}) + # The Lit files are configured once per architecture and static/dynamic + # selection. Each configuration expects the test binaries in a corresponding + # subdirectory. Generate subdirectory names based on the architecture name. + string(TOUPPER ${arch} ARCH_UPPER_CASE) + set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config) + set(CONFIG_NAME_DYNAMIC ${ARCH_UPPER_CASE}${OS_NAME}DynamicConfig) + # Closure to keep the values. function(generate_asan_tests test_objects test_suite testname) generate_compiler_rt_tests(${test_objects} ${test_suite} ${testname} ${arch} COMPILE_DEPS ${ASAN_UNITTEST_HEADERS} ${ASAN_IGNORELIST_FILE} - DEPS gtest asan + DEPS llvm_gtest asan KIND ${TEST_KIND} ${ARGN} ) set("${test_objects}" "${${test_objects}}" PARENT_SCOPE) endfunction() + set(TARGET_LINK_FLAGS) + get_target_link_flags_for_arch(${arch} TARGET_LINK_FLAGS) + set(ASAN_INST_TEST_OBJECTS) generate_asan_tests(ASAN_INST_TEST_OBJECTS AsanUnitTests "Asan-${arch}${TEST_KIND}-Test" - SUBDIR "default" - LINK_FLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS} + SUBDIR "${CONFIG_NAME}" + LINK_FLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS} ${TARGET_LINK_FLAGS} SOURCES ${ASAN_INST_TEST_SOURCES} CFLAGS ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} ${TEST_CFLAGS}) @@ -191,7 +202,7 @@ function(add_asan_tests arch test_runtime) set(ASAN_DYNAMIC_TEST_OBJECTS) generate_asan_tests(ASAN_DYNAMIC_TEST_OBJECTS AsanDynamicUnitTests "${dynamic_test_name}" - SUBDIR "dynamic" + SUBDIR "${CONFIG_NAME_DYNAMIC}" CFLAGS ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} -D_MT -D_DLL SOURCES ${ASAN_INST_TEST_SOURCES} LINK_FLAGS ${ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINK_FLAGS} @@ -201,10 +212,10 @@ function(add_asan_tests arch test_runtime) # Otherwise, reuse ASAN_INST_TEST_OBJECTS. add_compiler_rt_test(AsanDynamicUnitTests "${dynamic_test_name}" "${arch}" - SUBDIR "dynamic" + SUBDIR "${CONFIG_NAME_DYNAMIC}" OBJECTS ${ASAN_INST_TEST_OBJECTS} DEPS asan ${ASAN_INST_TEST_OBJECTS} - LINK_FLAGS ${ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINK_FLAGS} + LINK_FLAGS ${ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINK_FLAGS} ${TARGET_LINK_FLAGS} ) endif() endif() @@ -213,19 +224,19 @@ function(add_asan_tests arch test_runtime) set(ASAN_NOINST_TEST_OBJECTS) generate_asan_tests(ASAN_NOINST_TEST_OBJECTS AsanUnitTests "Asan-${arch}${TEST_KIND}-Noinst-Test" - SUBDIR "default" + SUBDIR "${CONFIG_NAME}" CFLAGS ${ASAN_UNITTEST_COMMON_CFLAGS} - LINK_FLAGS ${ASAN_UNITTEST_NOINST_LINK_FLAGS} + LINK_FLAGS ${ASAN_UNITTEST_NOINST_LINK_FLAGS} ${TARGET_LINK_FLAGS} SOURCES ${ASAN_NOINST_TEST_SOURCES} RUNTIME ${test_runtime}) set(ASAN_BENCHMARK_OBJECTS) generate_asan_tests(ASAN_BENCHMARK_OBJECTS AsanBenchmarks "Asan-${arch}${TEST_KIND}-Benchmark" - SUBDIR "default" + SUBDIR "${CONFIG_NAME}" CFLAGS ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} SOURCES ${ASAN_BENCHMARKS_SOURCES} - LINK_FLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS}) + LINK_FLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS} ${TARGET_LINK_FLAGS}) endfunction() if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID) @@ -256,6 +267,7 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID) set(ASAN_TEST_RUNTIME_OBJECTS $ $ + $ $ $ $ @@ -281,6 +293,7 @@ if(ANDROID) # Test w/o ASan instrumentation. Link it with ASan statically. add_executable(AsanNoinstTest # FIXME: .arch? $ + $ $ $ $ diff --git a/gnu/llvm/compiler-rt/lib/asan/tests/asan_interface_test.cpp b/gnu/llvm/compiler-rt/lib/asan/tests/asan_interface_test.cpp index ffc3226b643..021ebfb04b0 100644 --- a/gnu/llvm/compiler-rt/lib/asan/tests/asan_interface_test.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/tests/asan_interface_test.cpp @@ -90,7 +90,7 @@ TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) { TEST(AddressSanitizerInterface, GetHeapSizeTest) { // ASan allocator does not keep huge chunks in free list, but unmaps them. // The chunk should be greater than the quarantine size, - // otherwise it will be stuck in quarantine instead of being unmaped. + // otherwise it will be stuck in quarantine instead of being unmapped. static const size_t kLargeMallocSize = (1 << 28) + 1; // 256M free(Ident(malloc(kLargeMallocSize))); // Drain quarantine. size_t old_heap_size = __sanitizer_get_heap_size(); @@ -160,7 +160,6 @@ TEST(AddressSanitizerInterface, DeathCallbackTest) { #define BAD_ACCESS(ptr, offset) \ EXPECT_TRUE(__asan_address_is_poisoned(ptr + offset)) -#if !defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3 static const char* kUseAfterPoisonErrorMessage = "use-after-poison"; TEST(AddressSanitizerInterface, SimplePoisonMemoryRegionTest) { @@ -200,7 +199,6 @@ TEST(AddressSanitizerInterface, OverlappingPoisonMemoryRegionTest) { BAD_ACCESS(array, 96); free(array); } -#endif // !defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3 TEST(AddressSanitizerInterface, PushAndPopWithPoisoningTest) { // Vector of capacity 20 @@ -415,6 +413,9 @@ TEST(AddressSanitizerInterface, HandleNoReturnTest) { __asan_poison_memory_region(array, sizeof(array)); BAD_ACCESS(array, 20); __asan_handle_no_return(); + // Fake stack does not need to be unpoisoned. + if (__asan_get_current_fake_stack()) + return; // It unpoisons the whole thread stack. GOOD_ACCESS(array, 20); } diff --git a/gnu/llvm/compiler-rt/lib/asan/tests/asan_internal_interface_test.cpp b/gnu/llvm/compiler-rt/lib/asan/tests/asan_internal_interface_test.cpp index 218edaffb62..cb205e08301 100644 --- a/gnu/llvm/compiler-rt/lib/asan/tests/asan_internal_interface_test.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/tests/asan_internal_interface_test.cpp @@ -19,6 +19,27 @@ TEST(AddressSanitizerInternalInterface, SetShadow) { __asan_set_shadow_00((uptr)buffer.data(), buffer.size()); EXPECT_EQ(std::vector(buffer.size(), 0x00), buffer); + __asan_set_shadow_01((uptr)buffer.data(), buffer.size()); + EXPECT_EQ(std::vector(buffer.size(), 0x01), buffer); + + __asan_set_shadow_02((uptr)buffer.data(), buffer.size()); + EXPECT_EQ(std::vector(buffer.size(), 0x02), buffer); + + __asan_set_shadow_03((uptr)buffer.data(), buffer.size()); + EXPECT_EQ(std::vector(buffer.size(), 0x03), buffer); + + __asan_set_shadow_04((uptr)buffer.data(), buffer.size()); + EXPECT_EQ(std::vector(buffer.size(), 0x04), buffer); + + __asan_set_shadow_05((uptr)buffer.data(), buffer.size()); + EXPECT_EQ(std::vector(buffer.size(), 0x05), buffer); + + __asan_set_shadow_06((uptr)buffer.data(), buffer.size()); + EXPECT_EQ(std::vector(buffer.size(), 0x06), buffer); + + __asan_set_shadow_07((uptr)buffer.data(), buffer.size()); + EXPECT_EQ(std::vector(buffer.size(), 0x07), buffer); + __asan_set_shadow_f1((uptr)buffer.data(), buffer.size()); EXPECT_EQ(std::vector(buffer.size(), 0xf1), buffer); diff --git a/gnu/llvm/compiler-rt/lib/asan/tests/asan_mem_test.cpp b/gnu/llvm/compiler-rt/lib/asan/tests/asan_mem_test.cpp index e2af1b8d79a..5408a10a7c6 100644 --- a/gnu/llvm/compiler-rt/lib/asan/tests/asan_mem_test.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/tests/asan_mem_test.cpp @@ -37,18 +37,18 @@ void MemSetOOBTestTemplate(size_t length) { MEMSET(array + length, 0, zero); MEMSET(array + length + 1, 0, zero); - // try to memset bytes to the right of array + // try to memset bytes after array EXPECT_DEATH(MEMSET(array, 0, size + 1), RightOOBWriteMessage(0)); EXPECT_DEATH(MEMSET((char*)(array + length) - 1, element, 6), RightOOBWriteMessage(0)); EXPECT_DEATH(MEMSET(array + 1, element, size + sizeof(T)), RightOOBWriteMessage(0)); - // whole interval is to the right + // whole interval is after EXPECT_DEATH(MEMSET(array + length + 1, 0, 10), RightOOBWriteMessage(sizeof(T))); - // try to memset bytes to the left of array + // try to memset bytes before array EXPECT_DEATH(MEMSET((char*)array - 1, element, size), LeftOOBWriteMessage(1)); EXPECT_DEATH(MEMSET((char*)array - 5, 0, 6), @@ -58,11 +58,11 @@ void MemSetOOBTestTemplate(size_t length) { EXPECT_DEATH(memset(array - 5, element, size + 5 * sizeof(T)), LeftOOBWriteMessage(5 * sizeof(T))); } - // whole interval is to the left + // whole interval is before EXPECT_DEATH(MEMSET(array - 2, 0, sizeof(T)), LeftOOBWriteMessage(2 * sizeof(T))); - // try to memset bytes both to the left & to the right + // try to memset bytes both before & after EXPECT_DEATH(MEMSET((char*)array - 2, element, size + 4), LeftOOBWriteMessage(2)); @@ -114,7 +114,7 @@ TEST(AddressSanitizer, LargeOOBInMemset) { // fprintf(stderr, " large oob memset: %p %p %zd\n", x1, x2, size); // Do a memset on x1 with huge out-of-bound access that will end up in x2. EXPECT_DEATH(Ident(memset)(x1, 0, size * 2), - "is located 0 bytes to the right"); + "is located 0 bytes after"); delete [] x1; delete [] x2; return; @@ -143,25 +143,25 @@ void MemTransferOOBTestTemplate(size_t length) { M::transfer(dest, src - 1, zero); M::transfer(dest, src, zero); - // try to change mem to the right of dest + // try to change mem after dest EXPECT_DEATH(M::transfer(dest + 1, src, size), RightOOBWriteMessage(0)); EXPECT_DEATH(M::transfer((char*)(dest + length) - 1, src, 5), RightOOBWriteMessage(0)); - // try to change mem to the left of dest + // try to change mem before dest EXPECT_DEATH(M::transfer(dest - 2, src, size), LeftOOBWriteMessage(2 * sizeof(T))); EXPECT_DEATH(M::transfer((char*)dest - 3, src, 4), LeftOOBWriteMessage(3)); - // try to access mem to the right of src + // try to access mem after src EXPECT_DEATH(M::transfer(dest, src + 2, size), RightOOBReadMessage(0)); EXPECT_DEATH(M::transfer(dest, (char*)(src + length) - 3, 6), RightOOBReadMessage(0)); - // try to access mem to the left of src + // try to access mem before src EXPECT_DEATH(M::transfer(dest, src - 1, size), LeftOOBReadMessage(sizeof(T))); EXPECT_DEATH(M::transfer(dest, (char*)src - 6, 7), diff --git a/gnu/llvm/compiler-rt/lib/asan/tests/asan_noinst_test.cpp b/gnu/llvm/compiler-rt/lib/asan/tests/asan_noinst_test.cpp index 2f6b11bb6cb..4c103609c83 100644 --- a/gnu/llvm/compiler-rt/lib/asan/tests/asan_noinst_test.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/tests/asan_noinst_test.cpp @@ -11,19 +11,20 @@ // This test file should be compiled w/o asan instrumentation. //===----------------------------------------------------------------------===// -#include "asan_allocator.h" -#include "asan_internal.h" -#include "asan_mapping.h" -#include "asan_test_utils.h" -#include - #include +#include #include #include #include // for memset() + #include -#include #include +#include + +#include "asan_allocator.h" +#include "asan_internal.h" +#include "asan_mapping.h" +#include "asan_test_utils.h" using namespace __sanitizer; @@ -230,17 +231,8 @@ TEST(AddressSanitizer, ShadowRegionIsPoisonedTest) { } // Test __asan_load1 & friends. -TEST(AddressSanitizer, LoadStoreCallbacks) { - typedef void (*CB)(uptr p); - CB cb[2][5] = { - { - __asan_load1, __asan_load2, __asan_load4, __asan_load8, __asan_load16, - }, { - __asan_store1, __asan_store2, __asan_store4, __asan_store8, - __asan_store16, - } - }; - +typedef void (*CB)(uptr p); +static void TestLoadStoreCallbacks(CB cb[2][5]) { uptr buggy_ptr; __asan_test_only_reported_buggy_pointer = &buggy_ptr; @@ -270,3 +262,86 @@ TEST(AddressSanitizer, LoadStoreCallbacks) { } __asan_test_only_reported_buggy_pointer = 0; } + +TEST(AddressSanitizer, LoadStoreCallbacks) { + CB cb[2][5] = {{ + __asan_load1, + __asan_load2, + __asan_load4, + __asan_load8, + __asan_load16, + }, + { + __asan_store1, + __asan_store2, + __asan_store4, + __asan_store8, + __asan_store16, + }}; + TestLoadStoreCallbacks(cb); +} + +#if defined(__x86_64__) && \ + !(defined(SANITIZER_APPLE) || defined(SANITIZER_WINDOWS)) +// clang-format off + +#define CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(s, reg, op) \ + void CallAsanMemoryAccessAdd##reg##op##s(uptr address) { \ + asm("push %%" #reg " \n" \ + "mov %[x], %%" #reg " \n" \ + "call __asan_check_" #op "_add_" #s "_" #reg "\n" \ + "pop %%" #reg " \n" \ + : \ + : [x] "r"(address) \ + : "r8", "rdi"); \ + } + +#define TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, load) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, store) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, load) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, store) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, load) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, store) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, load) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, store) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, load) \ + CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, store) \ + \ + TEST(AddressSanitizer, LoadStoreCallbacksAddX86##reg) { \ + CB cb[2][5] = {{ \ + CallAsanMemoryAccessAdd##reg##load1, \ + CallAsanMemoryAccessAdd##reg##load2, \ + CallAsanMemoryAccessAdd##reg##load4, \ + CallAsanMemoryAccessAdd##reg##load8, \ + CallAsanMemoryAccessAdd##reg##load16, \ + }, \ + { \ + CallAsanMemoryAccessAdd##reg##store1, \ + CallAsanMemoryAccessAdd##reg##store2, \ + CallAsanMemoryAccessAdd##reg##store4, \ + CallAsanMemoryAccessAdd##reg##store8, \ + CallAsanMemoryAccessAdd##reg##store16, \ + }}; \ + TestLoadStoreCallbacks(cb); \ + } + +// Instantiate all but R10 and R11 callbacks. We are using PLTSafe class with +// the intrinsic, which guarantees that the code generation will never emit +// R10 or R11 callbacks. +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14) +TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15) + +// clang-format on +#endif diff --git a/gnu/llvm/compiler-rt/lib/asan/tests/asan_oob_test.cpp b/gnu/llvm/compiler-rt/lib/asan/tests/asan_oob_test.cpp index 6b178b5917d..56f573c1fc4 100644 --- a/gnu/llvm/compiler-rt/lib/asan/tests/asan_oob_test.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/tests/asan_oob_test.cpp @@ -30,7 +30,7 @@ NOINLINE void oob_test(int size, int off) { static std::string GetLeftOOBMessage(int off) { char str[100]; - sprintf(str, "is located.*%d byte.*to the left", off); + sprintf(str, "is located.*%d byte.*before", off); return str; } @@ -38,12 +38,12 @@ static std::string GetRightOOBMessage(int off) { char str[100]; #if !defined(_WIN32) // FIXME: Fix PR42868 and remove SEGV match. - sprintf(str, "is located.*%d byte.*to the right|SEGV", off); + sprintf(str, "is located.*%d byte.*after|SEGV", off); #else // `|` doesn't work in googletest's regexes on Windows, // see googletest/docs/advanced.md#regular-expression-syntax // But it's not needed on Windows anyways. - sprintf(str, "is located.*%d byte.*to the right", off); + sprintf(str, "is located.*%d byte.*after", off); #endif return str; } diff --git a/gnu/llvm/compiler-rt/lib/asan/tests/asan_str_test.cpp b/gnu/llvm/compiler-rt/lib/asan/tests/asan_str_test.cpp index 12b8e5a5e67..1bf6c3581d3 100644 --- a/gnu/llvm/compiler-rt/lib/asan/tests/asan_str_test.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/tests/asan_str_test.cpp @@ -51,7 +51,7 @@ std::string RightOOBReadMessage(OOBKind oob_kind, int oob_distance) { } // namespace // Input to a test is a zero-terminated string str with given length -// Accesses to the bytes to the left and to the right of str +// Accesses to the bytes before and after str // are presumed to produce OOB errors void StrLenOOBTestTemplate(char *str, size_t length, OOBKind oob_kind) { // Normal strlen calls @@ -62,7 +62,7 @@ void StrLenOOBTestTemplate(char *str, size_t length, OOBKind oob_kind) { } // Arg of strlen is not malloced, OOB access if (oob_kind != OOBKind::Global) { - // We don't insert RedZones to the left of global variables + // We don't insert RedZones before global variables EXPECT_DEATH(Ident(strlen(str - 1)), LeftOOBReadMessage(oob_kind, 1)); EXPECT_DEATH(Ident(strlen(str - 5)), LeftOOBReadMessage(oob_kind, 5)); } diff --git a/gnu/llvm/compiler-rt/lib/asan/tests/asan_test.cpp b/gnu/llvm/compiler-rt/lib/asan/tests/asan_test.cpp index eb61410d768..40b335d1346 100644 --- a/gnu/llvm/compiler-rt/lib/asan/tests/asan_test.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/tests/asan_test.cpp @@ -313,7 +313,7 @@ TEST(AddressSanitizer, SignalTest) { static void TestLargeMalloc(size_t size) { char buff[1024]; - sprintf(buff, "is located 1 bytes to the left of %lu-byte", (long)size); + sprintf(buff, "is located 1 bytes before %lu-byte", (long)size); EXPECT_DEATH(Ident((char*)malloc(size))[-1] = 0, buff); } @@ -329,7 +329,7 @@ TEST(AddressSanitizer, HugeMallocTest) { if (SANITIZER_WORDSIZE != 64 || ASAN_AVOID_EXPENSIVE_TESTS) return; size_t n_megs = 4100; EXPECT_DEATH(Ident((char*)malloc(n_megs << 20))[-1] = 0, - "is located 1 bytes to the left|" + "is located 1 bytes before|" "AddressSanitizer failed to allocate"); } #endif @@ -345,9 +345,9 @@ TEST(AddressSanitizer, memalign) { for (int align = 16; align <= (1 << 23); align *= 2) { size_t size = align * 5; EXPECT_DEATH(MemalignRun(align, size, -1), - "is located 1 bytes to the left"); + "is located 1 bytes before"); EXPECT_DEATH(MemalignRun(align, size, size + 1), - "is located 1 bytes to the right"); + "is located 1 bytes after"); } } #endif // SANITIZER_TEST_HAS_MEMALIGN @@ -623,7 +623,7 @@ NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) { #if !defined(__ANDROID__) && !defined(__arm__) && !defined(__aarch64__) && \ !defined(__mips__) && !defined(__mips64) && !defined(__s390__) && \ - !defined(__riscv) + !defined(__riscv) && !defined(__loongarch__) NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) { // create three red zones for these two stack objects. int a; @@ -646,9 +646,9 @@ TEST(AddressSanitizer, BuiltinLongJmpTest) { } } #endif // !defined(__ANDROID__) && !defined(__arm__) && - // !defined(__aarch64__) && !defined(__mips__) - // !defined(__mips64) && !defined(__s390__) - // !defined(__riscv) + // !defined(__aarch64__) && !defined(__mips__) && + // !defined(__mips64) && !defined(__s390__) && + // !defined(__riscv) && !defined(__loongarch__) TEST(AddressSanitizer, UnderscopeLongJmpTest) { static jmp_buf buf; @@ -734,7 +734,7 @@ TEST(AddressSanitizer, Store128Test) { EXPECT_DEATH(_mm_store_si128((__m128i*)p, value_wide), "WRITE of size 16"); EXPECT_DEATH(_mm_store_si128((__m128i*)p, value_wide), - "located 0 bytes to the right of 12-byte"); + "located 0 bytes after 12-byte"); free(a); } #endif @@ -747,7 +747,7 @@ std::string RightOOBErrorMessage(int oob_distance, bool is_write) { #if !GTEST_USES_SIMPLE_RE "buffer-overflow.*%s.*" #endif - "located %d bytes to the right", + "located %d bytes after", #if !GTEST_USES_SIMPLE_RE is_write ? "WRITE" : "READ", #endif @@ -771,7 +771,7 @@ std::string LeftOOBErrorMessage(int oob_distance, bool is_write) { #if !GTEST_USES_SIMPLE_RE ASAN_PCRE_DOTALL "%s.*" #endif - "located %d bytes to the left", + "located %d bytes before", #if !GTEST_USES_SIMPLE_RE is_write ? "WRITE" : "READ", #endif @@ -790,7 +790,7 @@ std::string LeftOOBReadMessage(int oob_distance) { std::string LeftOOBAccessMessage(int oob_distance) { assert(oob_distance > 0); char expected_str[100]; - sprintf(expected_str, "located %d bytes to the left", oob_distance); + sprintf(expected_str, "located %d bytes before", oob_distance); return std::string(expected_str); } @@ -812,7 +812,7 @@ char* MallocAndMemsetString(size_t size) { EXPECT_DEATH(READ_N_BYTES, \ ASAN_PCRE_DOTALL \ "AddressSanitizer: heap-buffer-overflow" \ - ".* is located 0 bytes to the right of 10-byte region"); \ + ".* is located 0 bytes after 10-byte region"); \ close(fd); \ delete [] x; \ @@ -1013,23 +1013,23 @@ TEST(AddressSanitizer, GlobalTest) { glob5[Ident(4)] = 0; EXPECT_DEATH(glob5[Ident(5)] = 0, - "0 bytes to the right of global variable.*glob5.* size 5"); + "0 bytes after global variable.*glob5.* size 5"); EXPECT_DEATH(glob5[Ident(5+6)] = 0, - "6 bytes to the right of global variable.*glob5.* size 5"); + "6 bytes after global variable.*glob5.* size 5"); Ident(static110); // avoid optimizations static110[Ident(0)] = 0; static110[Ident(109)] = 0; EXPECT_DEATH(static110[Ident(110)] = 0, - "0 bytes to the right of global variable"); + "0 bytes after global variable"); EXPECT_DEATH(static110[Ident(110+7)] = 0, - "7 bytes to the right of global variable"); + "7 bytes after global variable"); Ident(func_static15); // avoid optimizations func_static15[Ident(0)] = 0; EXPECT_DEATH(func_static15[Ident(15)] = 0, - "0 bytes to the right of global variable"); + "0 bytes after global variable"); EXPECT_DEATH(func_static15[Ident(15 + 9)] = 0, - "9 bytes to the right of global variable"); + "9 bytes after global variable"); Ident(fs1); Ident(fs2); @@ -1037,12 +1037,12 @@ TEST(AddressSanitizer, GlobalTest) { // We don't create left redzones, so this is not 100% guaranteed to fail. // But most likely will. - EXPECT_DEATH(fs2[Ident(-1)] = 0, "is located.*of global variable"); + EXPECT_DEATH(fs2[Ident(-1)] = 0, "is located.* global variable"); EXPECT_DEATH(Ident(Ident(ConstGlob)[8]), - "is located 1 bytes to the right of .*ConstGlob"); + "is located 1 bytes after .*ConstGlob"); EXPECT_DEATH(Ident(Ident(StaticConstGlob)[5]), - "is located 2 bytes to the right of .*StaticConstGlob"); + "is located 2 bytes after .*StaticConstGlob"); // call stuff from another file. GlobalsTest(0); diff --git a/gnu/llvm/compiler-rt/lib/asan/tests/asan_test_main.cpp b/gnu/llvm/compiler-rt/lib/asan/tests/asan_test_main.cpp index 245d07f87b5..136b752aebb 100644 --- a/gnu/llvm/compiler-rt/lib/asan/tests/asan_test_main.cpp +++ b/gnu/llvm/compiler-rt/lib/asan/tests/asan_test_main.cpp @@ -14,7 +14,7 @@ // Default ASAN_OPTIONS for the unit tests. extern "C" const char* __asan_default_options() { -#if SANITIZER_MAC +#if SANITIZER_APPLE // 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' // and make sure we do not overwhelm the syslog while testing. Also, let's @@ -33,21 +33,6 @@ extern "C" const char* __asan_default_options() { #endif } -namespace __sanitizer { -bool ReexecDisabled() { -#if __has_feature(address_sanitizer) && SANITIZER_MAC - // Allow re-exec in instrumented unit tests on Darwin. Technically, we only - // need this for 10.10 and below, where re-exec is required for the - // interceptors to work, but to avoid duplicating the version detection logic, - // let's just allow re-exec for all Darwin versions. On newer OS versions, - // returning 'false' doesn't do anything anyway, because we don't re-exec. - return false; -#else - return true; -#endif -} -} // namespace __sanitizer - int main(int argc, char **argv) { testing::GTEST_FLAG(death_test_style) = "threadsafe"; testing::InitGoogleTest(&argc, argv); diff --git a/gnu/llvm/compiler-rt/lib/asan/weak_symbols.txt b/gnu/llvm/compiler-rt/lib/asan/weak_symbols.txt index fe680f8a9a4..b087f4f78e2 100644 --- a/gnu/llvm/compiler-rt/lib/asan/weak_symbols.txt +++ b/gnu/llvm/compiler-rt/lib/asan/weak_symbols.txt @@ -2,6 +2,13 @@ ___asan_default_options ___asan_default_suppressions ___asan_on_error ___asan_set_shadow_00 +___asan_set_shadow_01 +___asan_set_shadow_02 +___asan_set_shadow_03 +___asan_set_shadow_04 +___asan_set_shadow_05 +___asan_set_shadow_06 +___asan_set_shadow_07 ___asan_set_shadow_f1 ___asan_set_shadow_f2 ___asan_set_shadow_f3 diff --git a/gnu/llvm/compiler-rt/lib/builtins/CMakeLists.txt b/gnu/llvm/compiler-rt/lib/builtins/CMakeLists.txt index 59d83631a5f..2fc70522895 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/lib/builtins/CMakeLists.txt @@ -4,20 +4,40 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) cmake_minimum_required(VERSION 3.13.4) + if ("${CMAKE_VERSION}" VERSION_LESS "3.20.0") + message(WARNING + "Your CMake version is ${CMAKE_VERSION}. Starting with LLVM 17.0.0, the " + "minimum version of CMake required to build LLVM will become 3.20.0, and " + "using an older CMake will become an error. Please upgrade your CMake to " + "at least 3.20.0 now to avoid issues in the future!") + endif() set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) project(CompilerRTBuiltins C ASM) set(COMPILER_RT_STANDALONE_BUILD TRUE) set(COMPILER_RT_BUILTINS_STANDALONE_BUILD TRUE) + + set(COMPILER_RT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..") + + set(LLVM_COMMON_CMAKE_UTILS "${COMPILER_RT_SOURCE_DIR}/../cmake") + + # Add path for custom modules list(INSERT CMAKE_MODULE_PATH 0 - "${CMAKE_SOURCE_DIR}/../../cmake" - "${CMAKE_SOURCE_DIR}/../../cmake/Modules") + "${COMPILER_RT_SOURCE_DIR}/cmake" + "${COMPILER_RT_SOURCE_DIR}/cmake/Modules" + "${LLVM_COMMON_CMAKE_UTILS}" + "${LLVM_COMMON_CMAKE_UTILS}/Modules" + ) + include(base-config-ix) include(CompilerRTUtils) - load_llvm_config() + if (NOT LLVM_RUNTIMES_BUILD) + load_llvm_config() + endif() construct_compiler_rt_default_triple() + include(SetPlatformToolchainTools) if(APPLE) include(CompilerRTDarwinUtils) endif() @@ -25,15 +45,6 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) include(UseLibtool) endif() include(AddCompilerRT) - - if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") - set(CMAKE_C_ARCHIVE_CREATE " -X32_64 qc ") - set(CMAKE_CXX_ARCHIVE_CREATE " -X32_64 qc ") - set(CMAKE_C_ARCHIVE_APPEND " -X32_64 q ") - set(CMAKE_CXX_ARCHIVE_APPEND " -X32_64 q ") - set(CMAKE_C_ARCHIVE_FINISH " -X32_64 ") - set(CMAKE_CXX_ARCHIVE_FINISH " -X32_64 ") - endif() endif() if (COMPILER_RT_STANDALONE_BUILD) @@ -47,6 +58,7 @@ if (COMPILER_RT_STANDALONE_BUILD) endif() include(builtin-config-ix) +include(CMakePushCheckState) if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") include(CompilerRTAIXUtils) @@ -179,6 +191,12 @@ set(GENERIC_SOURCES umodti3.c ) +# We only build BF16 files when "__bf16" is available. +set(BF16_SOURCES + truncdfbf2.c + truncsfbf2.c +) + # TODO: Several "tf" files (and divtc3.c, but not multc3.c) are in # GENERIC_SOURCES instead of here. set(GENERIC_TF_SOURCES @@ -362,7 +380,9 @@ else () # MSVC set(i386_SOURCES ${GENERIC_SOURCES} ${x86_ARCH_SOURCES}) endif () # if (NOT MSVC) -set(arm_SOURCES + +# builtin support for Targets that have Arm state or have Thumb2 +set(arm_or_thumb2_base_SOURCES arm/fp_mode.c arm/bswapdi2.S arm/bswapsi2.S @@ -372,6 +392,13 @@ set(arm_SOURCES arm/divmodsi4.S arm/divsi3.S arm/modsi3.S + arm/udivmodsi4.S + arm/udivsi3.S + arm/umodsi3.S + ${GENERIC_SOURCES} +) + +set(arm_sync_SOURCES arm/sync_fetch_and_add_4.S arm/sync_fetch_and_add_8.S arm/sync_fetch_and_and_4.S @@ -392,13 +419,11 @@ set(arm_SOURCES arm/sync_fetch_and_umin_8.S arm/sync_fetch_and_xor_4.S arm/sync_fetch_and_xor_8.S - arm/udivmodsi4.S - arm/udivsi3.S - arm/umodsi3.S - ${GENERIC_SOURCES} ) -set(thumb1_SOURCES +# builtin support for Thumb-only targets with very limited Thumb2 technology, +# such as v6-m and v8-m.baseline +set(thumb1_base_SOURCES arm/divsi3.S arm/udivsi3.S arm/comparesf2.S @@ -477,6 +502,8 @@ set(arm_Thumb1_VFPv2_SP_SOURCES set(arm_Thumb1_icache_SOURCES arm/sync_synchronize.S ) + +# thumb1 calling into Arm to cover support set(arm_Thumb1_SOURCES ${arm_Thumb1_JT_SOURCES} ${arm_Thumb1_SjLj_EH_SOURCES} @@ -485,6 +512,13 @@ set(arm_Thumb1_SOURCES ${arm_Thumb1_icache_SOURCES} ) +# base functionality for Arm Targets prior to Arm v7-a and Armv6-m such as v6, +# v5t, v4t +set(arm_min_SOURCES + ${arm_or_thumb2_base_SOURCES} + ${arm_EABI_SOURCES} +) + if(MINGW) set(arm_SOURCES arm/aeabi_idivmod.S @@ -492,19 +526,24 @@ if(MINGW) arm/aeabi_uidivmod.S arm/aeabi_uldivmod.S arm/chkstk.S - mingw_fixfloat.c - ${arm_SOURCES} + ${arm_or_thumb2_base_SOURCES} + ${arm_sync_SOURCES} + ) + + set(thumb1_SOURCES + ${thumb1_base_SOURCES} ) elseif(NOT WIN32) # TODO the EABI sources should only be added to EABI targets set(arm_SOURCES - ${arm_SOURCES} + ${arm_or_thumb2_base_SOURCES} + ${arm_sync_SOURCES} ${arm_EABI_SOURCES} ${arm_Thumb1_SOURCES} ) set(thumb1_SOURCES - ${thumb1_SOURCES} + ${thumb1_base_SOURCES} ${arm_EABI_SOURCES} ) endif() @@ -551,6 +590,9 @@ if (MINGW) ) endif() +set(armv4t_SOURCES ${arm_min_SOURCES}) +set(armv5te_SOURCES ${arm_min_SOURCES}) +set(armv6_SOURCES ${arm_min_SOURCES}) set(armhf_SOURCES ${arm_SOURCES}) set(armv7_SOURCES ${arm_SOURCES}) set(armv7s_SOURCES ${arm_SOURCES}) @@ -566,6 +608,18 @@ set(armv7em_SOURCES ${arm_SOURCES}) set(armv8m.main_SOURCES ${arm_SOURCES}) set(armv8.1m.main_SOURCES ${arm_SOURCES}) +# 8-bit AVR MCU +set(avr_SOURCES + avr/mulqi3.S + avr/mulhi3.S + avr/exit.S + avr/divmodhi4.S + avr/udivmodhi4.S + avr/divmodqi4.S + avr/udivmodqi4.S + ${GENERIC_SOURCES} +) + # hexagon arch set(hexagon_SOURCES hexagon/common_entry_exit_abi1.S @@ -598,6 +652,14 @@ set(hexagon_SOURCES ${GENERIC_TF_SOURCES} ) +set(loongarch_SOURCES + loongarch/fp_mode.c + ${GENERIC_SOURCES} + ${GENERIC_TF_SOURCES} +) +set(loongarch64_SOURCES + ${loongarch_SOURCES} +) set(mips_SOURCES ${GENERIC_SOURCES}) set(mipsel_SOURCES ${mips_SOURCES}) @@ -608,6 +670,8 @@ set(mips64el_SOURCES ${GENERIC_TF_SOURCES} set(powerpc_SOURCES ${GENERIC_SOURCES}) +set(powerpcspe_SOURCES ${GENERIC_SOURCES}) + set(powerpc64_SOURCES ppc/divtc3.c ppc/fixtfdi.c @@ -633,6 +697,7 @@ endif() set(powerpc64le_SOURCES ${powerpc64_SOURCES}) set(riscv_SOURCES + riscv/fp_mode.c riscv/save.S riscv/restore.S ${GENERIC_SOURCES} @@ -674,8 +739,11 @@ if (APPLE) darwin_add_builtin_libraries(${BUILTIN_SUPPORTED_OS}) else () set(BUILTIN_CFLAGS "") + add_security_warnings(BUILTIN_CFLAGS 0) - append_list_if(COMPILER_RT_HAS_FLOAT16 -DCOMPILER_RT_HAS_FLOAT16 BUILTIN_CFLAGS) + if (COMPILER_RT_HAS_FCF_PROTECTION_FLAG) + append_list_if(COMPILER_RT_ENABLE_CET -fcf-protection=full BUILTIN_CFLAGS) + endif() append_list_if(COMPILER_RT_HAS_STD_C11_FLAG -std=c11 BUILTIN_CFLAGS) @@ -700,11 +768,19 @@ else () append_list_if(COMPILER_RT_HAS_VISIBILITY_HIDDEN_FLAG VISIBILITY_HIDDEN BUILTIN_DEFS) endif() + if(COMPILER_RT_DISABLE_AARCH64_FMV) + list(APPEND BUILTIN_DEFS DISABLE_AARCH64_FMV) + endif() + append_list_if(COMPILER_RT_HAS_ASM_LSE HAS_ASM_LSE BUILTIN_DEFS) foreach (arch ${BUILTIN_SUPPORTED_ARCH}) if (CAN_TARGET_${arch}) + cmake_push_check_state() + # TODO: we should probably make most of the checks in builtin-config depend on the target flags. + message(STATUS "Performing additional configure checks with target flags: ${TARGET_${arch}_CFLAGS}") set(BUILTIN_CFLAGS_${arch} ${BUILTIN_CFLAGS}) + list(APPEND CMAKE_REQUIRED_FLAGS ${TARGET_${arch}_CFLAGS} ${BUILTIN_CFLAGS_${arch}}) # For ARM archs, exclude any VFP builtins if VFP is not supported if (${arch} MATCHES "^(arm|armhf|armv7|armv7s|armv7k|armv7m|armv7em|armv8m.main|armv8.1m.main)$") string(REPLACE ";" " " _TARGET_${arch}_CFLAGS "${TARGET_${arch}_CFLAGS}") @@ -717,12 +793,21 @@ else () SOURCE "#if !(__ARM_FP & 0x8) #error No double-precision support! #endif - int main() { return 0; }") + int main(void) { return 0; }") if(NOT COMPILER_RT_HAS_${arch}_VFP_DP) list(REMOVE_ITEM ${arch}_SOURCES ${arm_Thumb1_VFPv2_DP_SOURCES}) endif() endif() endif() + check_c_source_compiles("_Float16 foo(_Float16 x) { return x; }" + COMPILER_RT_HAS_${arch}_FLOAT16) + append_list_if(COMPILER_RT_HAS_${arch}_FLOAT16 -DCOMPILER_RT_HAS_FLOAT16 BUILTIN_CFLAGS_${arch}) + check_c_source_compiles("__bf16 foo(__bf16 x) { return x; }" + COMPILER_RT_HAS_${arch}_BFLOAT16) + # Build BF16 files only when "__bf16" is available. + if(COMPILER_RT_HAS_${arch}_BFLOAT16) + list(APPEND ${arch}_SOURCES ${BF16_SOURCES}) + endif() # Remove a generic C builtin when an arch-specific builtin is specified. filter_builtin_sources(${arch}_SOURCES ${arch}) @@ -757,6 +842,7 @@ else () DEFS ${BUILTIN_DEFS} CFLAGS ${BUILTIN_CFLAGS_${arch}} PARENT_TARGET builtins) + cmake_pop_check_state() endif () endforeach () endif () @@ -796,7 +882,7 @@ if(COMPILER_RT_BUILD_STANDALONE_LIBATOMIC) # archive, i.e., libatomic.a. Once cmake adds support of such usage for AIX, # this ad-hoc part can be removed. if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") - archive_aix_libatomic(clang_rt.atomic + archive_aix_libatomic(clang_rt.atomic libatomic ARCHS ${BUILTIN_SUPPORTED_ARCH} PARENT_TARGET builtins-standalone-atomic) endif() diff --git a/gnu/llvm/compiler-rt/lib/builtins/README.txt b/gnu/llvm/compiler-rt/lib/builtins/README.txt index d66d725e7ab..53d656d5086 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/README.txt +++ b/gnu/llvm/compiler-rt/lib/builtins/README.txt @@ -271,8 +271,8 @@ switchu8 // There is no C interface to the *_vfp_d8_d15_regs functions. There are // called in the prolog and epilog of Thumb1 functions. When the C++ ABI use -// SJLJ for exceptions, each function with a catch clause or destuctors needs -// to save and restore all registers in it prolog and epliog. But there is +// SJLJ for exceptions, each function with a catch clause or destructors needs +// to save and restore all registers in it prolog and epilog. But there is // no way to access vector and high float registers from thumb1 code, so the // compiler must add call outs to these helper functions in the prolog and // epilog. @@ -311,9 +311,9 @@ double __floatsidfvfp(int a); // Appears to convert from float __floatsisfvfp(int a); // Appears to convert from // int to float. double __floatunssidfvfp(unsigned int a); // Appears to convert from - // unisgned int to double. + // unsigned int to double. float __floatunssisfvfp(unsigned int a); // Appears to convert from - // unisgned int to float. + // unsigned int to float. int __gedf2vfp(double a, double b); // Appears to return __gedf2 // (a >= b) int __gesf2vfp(float a, float b); // Appears to return __gesf2 diff --git a/gnu/llvm/compiler-rt/lib/builtins/aarch64/fp_mode.c b/gnu/llvm/compiler-rt/lib/builtins/aarch64/fp_mode.c index 94c2ff3bb26..03d75cd8be6 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/aarch64/fp_mode.c +++ b/gnu/llvm/compiler-rt/lib/builtins/aarch64/fp_mode.c @@ -27,7 +27,7 @@ CRT_FE_ROUND_MODE __attribute__((weak)) __aarch64_fe_default_rmode = CRT_FE_TONEAREST; #endif -CRT_FE_ROUND_MODE __fe_getround() { +CRT_FE_ROUND_MODE __fe_getround(void) { #ifdef __ARM_FP uint64_t fpcr; __asm__ __volatile__("mrs %0, fpcr" : "=r" (fpcr)); @@ -48,7 +48,7 @@ CRT_FE_ROUND_MODE __fe_getround() { #endif } -int __fe_raise_inexact() { +int __fe_raise_inexact(void) { #ifdef __ARM_FP uint64_t fpsr; __asm__ __volatile__("mrs %0, fpsr" : "=r" (fpsr)); diff --git a/gnu/llvm/compiler-rt/lib/builtins/apple_versioning.c b/gnu/llvm/compiler-rt/lib/builtins/apple_versioning.c index f87b42820c1..83d419418f2 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/apple_versioning.c +++ b/gnu/llvm/compiler-rt/lib/builtins/apple_versioning.c @@ -138,13 +138,13 @@ NOT_HERE_BEFORE_10_6(__udivti3) NOT_HERE_BEFORE_10_6(__umoddi3) NOT_HERE_BEFORE_10_6(__umodti3) -#if __ppc__ +#if __powerpc__ NOT_HERE_BEFORE_10_6(__gcc_qadd) NOT_HERE_BEFORE_10_6(__gcc_qdiv) NOT_HERE_BEFORE_10_6(__gcc_qmul) NOT_HERE_BEFORE_10_6(__gcc_qsub) NOT_HERE_BEFORE_10_6(__trampoline_setup) -#endif // __ppc__ +#endif // __powerpc__ NOT_HERE_IN_10_8_AND_EARLIER(__atomic_compare_exchange) NOT_HERE_IN_10_8_AND_EARLIER(__atomic_compare_exchange_1) diff --git a/gnu/llvm/compiler-rt/lib/builtins/arm/fp_mode.c b/gnu/llvm/compiler-rt/lib/builtins/arm/fp_mode.c index f356e0b1316..064f4e94fb8 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/arm/fp_mode.c +++ b/gnu/llvm/compiler-rt/lib/builtins/arm/fp_mode.c @@ -27,7 +27,7 @@ CRT_FE_ROUND_MODE __attribute__((weak)) __arm_fe_default_rmode = CRT_FE_TONEAREST; #endif -CRT_FE_ROUND_MODE __fe_getround() { +CRT_FE_ROUND_MODE __fe_getround(void) { #ifdef __ARM_FP uint32_t fpscr; __asm__ __volatile__("vmrs %0, fpscr" : "=r" (fpscr)); @@ -48,7 +48,7 @@ CRT_FE_ROUND_MODE __fe_getround() { #endif } -int __fe_raise_inexact() { +int __fe_raise_inexact(void) { #ifdef __ARM_FP uint32_t fpscr; __asm__ __volatile__("vmrs %0, fpscr" : "=r" (fpscr)); diff --git a/gnu/llvm/compiler-rt/lib/builtins/arm/sync-ops.h b/gnu/llvm/compiler-rt/lib/builtins/arm/sync-ops.h index c9623249e5d..dca201d8aef 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/arm/sync-ops.h +++ b/gnu/llvm/compiler-rt/lib/builtins/arm/sync-ops.h @@ -14,35 +14,41 @@ #include "../assembly.h" +#if __ARM_ARCH >= 7 +#define DMB dmb +#elif __ARM_ARCH >= 6 +#define DMB mcr p15, #0, r0, c7, c10, #5 +#else +#error DMB is only supported on ARMv6+ +#endif + #define SYNC_OP_4(op) \ .p2align 2; \ - .thumb; \ .syntax unified; \ - DEFINE_COMPILERRT_THUMB_FUNCTION(__sync_fetch_and_##op) \ - dmb; \ + DEFINE_COMPILERRT_FUNCTION(__sync_fetch_and_##op) \ + DMB; \ mov r12, r0; \ LOCAL_LABEL(tryatomic_##op) : ldrex r0, [r12]; \ op(r2, r0, r1); \ strex r3, r2, [r12]; \ cmp r3, #0; \ bne LOCAL_LABEL(tryatomic_##op); \ - dmb; \ + DMB; \ bx lr #define SYNC_OP_8(op) \ .p2align 2; \ - .thumb; \ .syntax unified; \ - DEFINE_COMPILERRT_THUMB_FUNCTION(__sync_fetch_and_##op) \ + DEFINE_COMPILERRT_FUNCTION(__sync_fetch_and_##op) \ push {r4, r5, r6, lr}; \ - dmb; \ + DMB; \ mov r12, r0; \ LOCAL_LABEL(tryatomic_##op) : ldrexd r0, r1, [r12]; \ op(r4, r5, r0, r1, r2, r3); \ strexd r6, r4, r5, [r12]; \ cmp r6, #0; \ bne LOCAL_LABEL(tryatomic_##op); \ - dmb; \ + DMB; \ pop { r4, r5, r6, pc } #define MINMAX_4(rD, rN, rM, cmp_kind) \ diff --git a/gnu/llvm/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S b/gnu/llvm/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S index a3c0a73466e..e1c171262a7 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S +++ b/gnu/llvm/compiler-rt/lib/builtins/arm/truncdfsf2vfp.S @@ -11,9 +11,9 @@ // // extern float __truncdfsf2vfp(double a); // -// Converts double precision float to signle precision result. +// Converts double precision float to single precision result. // Uses Darwin calling convention where a double precision parameter is -// passed in a R0/R1 pair and a signle precision result is returned in R0. +// passed in a R0/R1 pair and a single precision result is returned in R0. // .syntax unified .p2align 2 diff --git a/gnu/llvm/compiler-rt/lib/builtins/assembly.h b/gnu/llvm/compiler-rt/lib/builtins/assembly.h index 9c015059af5..69a3d8620f9 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/assembly.h +++ b/gnu/llvm/compiler-rt/lib/builtins/assembly.h @@ -14,6 +14,12 @@ #ifndef COMPILERRT_ASSEMBLY_H #define COMPILERRT_ASSEMBLY_H +#if defined(__linux__) && defined(__CET__) +#if __has_include() +#include +#endif +#endif + #if defined(__APPLE__) && defined(__aarch64__) #define SEPARATOR %% #else diff --git a/gnu/llvm/compiler-rt/lib/builtins/atomic.c b/gnu/llvm/compiler-rt/lib/builtins/atomic.c index 64bf72dfa34..852bb20f086 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/atomic.c +++ b/gnu/llvm/compiler-rt/lib/builtins/atomic.c @@ -92,6 +92,8 @@ __inline static void lock(Lock *l) { OSSpinLockLock(l); } static Lock locks[SPINLOCK_COUNT]; // initialized to OS_SPINLOCK_INIT which is 0 #else +_Static_assert(__atomic_always_lock_free(sizeof(uintptr_t), 0), + "Implementation assumes lock-free pointer-size cmpxchg"); typedef _Atomic(uintptr_t) Lock; /// Unlock a lock. This is a release operation. __inline static void unlock(Lock *l) { @@ -336,6 +338,18 @@ OPTIMISED_CASES return tmp; \ } +#define ATOMIC_RMW_NAND(n, lockfree, type) \ + type __atomic_fetch_nand_##n(type *ptr, type val, int model) { \ + if (lockfree(ptr)) \ + return __c11_atomic_fetch_nand((_Atomic(type) *)ptr, val, model); \ + Lock *l = lock_for_pointer(ptr); \ + lock(l); \ + type tmp = *ptr; \ + *ptr = ~(tmp & val); \ + unlock(l); \ + return tmp; \ + } + #define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW(n, lockfree, type, add, +) OPTIMISED_CASES #undef OPTIMISED_CASE @@ -351,3 +365,9 @@ OPTIMISED_CASES #define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW(n, lockfree, type, xor, ^) OPTIMISED_CASES #undef OPTIMISED_CASE +// Allow build with clang without __c11_atomic_fetch_nand builtin (pre-14) +#if __has_builtin(__c11_atomic_fetch_nand) +#define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW_NAND(n, lockfree, type) +OPTIMISED_CASES +#undef OPTIMISED_CASE +#endif diff --git a/gnu/llvm/compiler-rt/lib/builtins/avr/divmodhi4.S b/gnu/llvm/compiler-rt/lib/builtins/avr/divmodhi4.S new file mode 100644 index 00000000000..37171331f4b --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/builtins/avr/divmodhi4.S @@ -0,0 +1,57 @@ +//===------------- divmodhi4.S - sint16 div & mod -------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// As described at +// https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention, the +// prototype is `struct {sint16, sint16} __divmodhi4(sint16, sint16)`. +// The sint16 quotient is returned via R23:R22, and the sint16 remainder is +// returned via R25:R24, while registers R21/R26/27/Rtmp and bit T in SREG +// are clobbered. +// +//===----------------------------------------------------------------------===// + + .text + .align 2 + +#ifdef __AVR_TINY__ + .set __tmp_reg__, 16 +#else + .set __tmp_reg__, 0 +#endif + + .globl __divmodhi4 + .type __divmodhi4, @function + +__divmodhi4: + bst r25, 7 + mov __tmp_reg__, r23 + brtc __divmodhi4_a + com __tmp_reg__ + rcall __divmodhi4_b + +__divmodhi4_a: + sbrc r23, 7 + rcall __divmodhi4_c + rcall __udivmodhi4 ; Call __udivmodhi4 to do real calculation. + sbrc __tmp_reg__, 7 + rcall __divmodhi4_c + brtc __divmodhi4_exit + +__divmodhi4_b: + com r25 + neg r24 + sbci r25, 255 + ret ; Return quotient via R23:R22 and remainder via R25:R24. + +__divmodhi4_c: + com r23 + neg r22 + sbci r23, 255 + +__divmodhi4_exit: + ret ; Return quotient via R23:R22 and remainder via R25:r24. diff --git a/gnu/llvm/compiler-rt/lib/builtins/avr/divmodqi4.S b/gnu/llvm/compiler-rt/lib/builtins/avr/divmodqi4.S new file mode 100644 index 00000000000..66cfc0c69bb --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/builtins/avr/divmodqi4.S @@ -0,0 +1,44 @@ +//===------------- divmodqi4.S - sint8 div & mod --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// As described at +// https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention, the +// prototype is `struct {sint8, sint8} __divmodqi4(sint8, sint8)`. +// The sint8 quotient is returned via R24, and the sint8 remainder is returned +// via R25, while registers R23/Rtmp and bit T in SREG are clobbered. +// +//===----------------------------------------------------------------------===// + + .text + .align 2 + +#ifdef __AVR_TINY__ + .set __tmp_reg__, 16 +#else + .set __tmp_reg__, 0 +#endif + + .globl __divmodqi4 + .type __divmodqi4, @function + +__divmodqi4: + bst r24, 7 + mov __tmp_reg__, r24 + eor __tmp_reg__, r22 + sbrc r24, 7 + neg r24 + sbrc r22, 7 + neg r22 + rcall __udivmodqi4 ; Call __udivmodqi4 to do real calculation. + brtc __divmodqi4_1 + neg r25 + +__divmodqi4_1: + sbrc __tmp_reg__, 7 + neg r24 + ret ; Return quotient via R24 and remainder via R25. diff --git a/gnu/llvm/compiler-rt/lib/builtins/avr/exit.S b/gnu/llvm/compiler-rt/lib/builtins/avr/exit.S new file mode 100644 index 00000000000..3cd9c5dafde --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/builtins/avr/exit.S @@ -0,0 +1,18 @@ +//===------------ exit.S - global terminator for AVR ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + + .text + .align 2 + + .globl _exit + .type _exit, @function + +_exit: + cli ; Disable all interrupts. +__stop_program: + rjmp __stop_program ; Fall into an infinite loop. diff --git a/gnu/llvm/compiler-rt/lib/builtins/avr/mulhi3.S b/gnu/llvm/compiler-rt/lib/builtins/avr/mulhi3.S new file mode 100644 index 00000000000..d65f52ff27b --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/builtins/avr/mulhi3.S @@ -0,0 +1,71 @@ +//===------------ mulhi3.S - int16 multiplication -------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// The corresponding C code is something like: +// +// int __mulhi3(int A, int B) { +// int S = 0; +// while (A != 0) { +// if (A & 1) +// S += B; +// A = ((unsigned int) A) >> 1; +// B <<= 1; +// } +// return S; +// } +// +// __mulhi3 has special ABI, as the implementation of libgcc, R25:R24 is used +// to return result, while Rtmp/R21/R22/R23 are clobbered. +// +//===----------------------------------------------------------------------===// + + .text + .align 2 + +#ifdef __AVR_TINY__ + .set __tmp_reg__, 16 + .set __zero_reg__, 17 +#else + .set __tmp_reg__, 0 + .set __zero_reg__, 1 +#endif + + .globl __mulhi3 + .type __mulhi3, @function + +__mulhi3: + ; Use Rzero:Rtmp to store the result. + clr __tmp_reg__ + clr __zero_reg__ ; S = 0; + +__mulhi3_loop: + clr r21 + cp r24, r21 + cpc r25, r21 + breq __mulhi3_end ; while (A != 0) { + + mov r21, r24 + andi r21, 1 + breq __mulhi3_loop_a ; if (A & 1) + add __tmp_reg__, r22 + adc __zero_reg__, r23 ; S += B; + +__mulhi3_loop_a: + lsr r25 + ror r24 ; A = ((unsigned int) A) >> 1; + lsl r22 + rol r23 ; B <<= 1; + rjmp __mulhi3_loop ; } + +__mulhi3_end: + ; Return the result via R25:R24. + mov r24, __tmp_reg__ + mov r25, __zero_reg__ + ; Restore __zero_reg__ to 0. + clr __zero_reg__ + ret ; return S; diff --git a/gnu/llvm/compiler-rt/lib/builtins/avr/mulqi3.S b/gnu/llvm/compiler-rt/lib/builtins/avr/mulqi3.S new file mode 100644 index 00000000000..914735cc645 --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/builtins/avr/mulqi3.S @@ -0,0 +1,53 @@ +//===------------ mulhi3.S - int8 multiplication --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// The corresponding C code is something like: +// +// char __mulqi3(char A, char B) { +// int S = 0; +// while (A != 0) { +// if (A & 1) +// S += B; +// B <<= 1; +// A = ((unsigned char) A) >> 1; +// } +// return S; +// } +// +// __mulqi3 has special ABI, as the implementation of libgcc, the result is +// returned via R24, while Rtmp and R22 are clobbered. +// +//===----------------------------------------------------------------------===// + + .text + .align 2 + +#ifdef __AVR_TINY__ + .set __tmp_reg__, 16 +#else + .set __tmp_reg__, 0 +#endif + + .globl __mulqi3 + .type __mulqi3, @function + +__mulqi3: + clr __tmp_reg__ ; S = 0; + +__mulqi3_loop: + cpi r24, 0 + breq __mulqi3_end ; while (A != 0) { + sbrc r24, 0 ; if (A & 1) + add __tmp_reg__, r22 ; S += B; + add r22, r22 ; B <<= 1; + lsr r24 ; A = ((unsigned char) A) >> 1; + rjmp __mulqi3_loop ; } + +__mulqi3_end: + mov r24, __tmp_reg__ + ret ; return S; diff --git a/gnu/llvm/compiler-rt/lib/builtins/avr/udivmodhi4.S b/gnu/llvm/compiler-rt/lib/builtins/avr/udivmodhi4.S new file mode 100644 index 00000000000..0e52b86ec79 --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/builtins/avr/udivmodhi4.S @@ -0,0 +1,49 @@ +//===------------ udivmodhi4.S - uint16 div & mod -------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// As described at +// https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention, the +// prototype is `struct {uint16, uint16} __udivmodhi4(uint16, uint16)`. +// The uint16 quotient is returned via R23:R22, and the uint16 remainder is +// returned via R25:R24, while R21/R26/R27 are clobbered. +// +//===----------------------------------------------------------------------===// + + .text + .align 2 + + .globl __udivmodhi4 + .type __udivmodhi4, @function + +__udivmodhi4: + sub r26, r26 + sub r27, r27 ; Initialize the remainder to zero. + ldi r21, 17 ; Only loop 16 rounds for uint16. + +__udivmodhi4_loop: + adc r24, r24 + adc r25, r25 + dec r21 + breq __udivmodhi4_end + adc r26, r26 + adc r27, r27 + cp r26, r22 + cpc r27, r23 ; Compare with the divisor. + brcs __udivmodhi4_loop + sub r26, r22 + sbc r27, r23 ; Subtract the divisor. + rjmp __udivmodhi4_loop + +__udivmodhi4_end: + com r24 + com r25 + mov r22, r24 + mov r23, r25 ; The quotient is returned in R23:R22. + mov r24, r26 + mov r25, r27 ; The remainder is returned in in R25:R24. + ret diff --git a/gnu/llvm/compiler-rt/lib/builtins/avr/udivmodqi4.S b/gnu/llvm/compiler-rt/lib/builtins/avr/udivmodqi4.S new file mode 100644 index 00000000000..99aec344293 --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/builtins/avr/udivmodqi4.S @@ -0,0 +1,39 @@ +//===------------ udivmodqi4.S - uint8 div & mod --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// As described at +// https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention, the +// prototype is `struct {uint8, uint8} __udivmodqi4(uint8, uint8)`. +// The uint8 quotient is returned via R24, and the uint8 remainder is returned +// via R25, while R23 is clobbered. +// +//===----------------------------------------------------------------------===// + + .text + .align 2 + + .globl __udivmodqi4 + .type __udivmodqi4, @function + +__udivmodqi4: + sub r25, r25 ; Initialize the remainder to zero. + ldi r23, 9 ; Only loop 8 rounds for uint8. + +__udivmodqi4_loop: + adc r24, r24 + dec r23 + breq __udivmodqi4_end + adc r25, r25 + cp r25, r22 ; Compare with the divisor. + brcs __udivmodqi4_loop + sub r25, r22 ; Subtract the divisor. + rjmp __udivmodqi4_loop + +__udivmodqi4_end: + com r24 ; The uint8 quotient is returned via R24. + ret ; The uint8 remainder is returned via R25. diff --git a/gnu/llvm/compiler-rt/lib/builtins/cpu_model.c b/gnu/llvm/compiler-rt/lib/builtins/cpu_model.c index 6ee42911b20..f5ad530c7e8 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/cpu_model.c +++ b/gnu/llvm/compiler-rt/lib/builtins/cpu_model.c @@ -9,14 +9,25 @@ // This file is based on LLVM's lib/Support/Host.cpp. // It implements the operating system Host concept and builtin // __cpu_model for the compiler_rt library for x86 and -// __aarch64_have_lse_atomics for AArch64. +// __aarch64_have_lse_atomics, __aarch64_cpu_features for AArch64. // //===----------------------------------------------------------------------===// -#if defined(HAVE_INIT_PRIORITY) -#define CONSTRUCTOR_ATTRIBUTE __attribute__((__constructor__ 101)) -#elif __has_attribute(__constructor__) -#define CONSTRUCTOR_ATTRIBUTE __attribute__((__constructor__)) +#ifndef __has_attribute +#define __has_attribute(attr) 0 +#endif + +#if __has_attribute(constructor) +#if __GNUC__ >= 9 +// Ordinarily init priorities below 101 are disallowed as they are reserved for the +// implementation. However, we are the implementation, so silence the diagnostic, +// since it doesn't apply to us. +#pragma GCC diagnostic ignored "-Wprio-ctor-dtor" +#endif +// We're choosing init priority 90 to force our constructors to run before any +// constructors in the end user application (starting at priority 101). This value +// matches the libgcc choice for the same functions. +#define CONSTRUCTOR_ATTRIBUTE __attribute__((constructor(90))) #else // FIXME: For MSVC, we should make a function pointer global in .CRT$X?? so that // this runs during initialization. @@ -37,10 +48,6 @@ #include #endif -#ifndef __has_attribute -#define __has_attribute(attr) 0 -#endif - enum VendorSignatures { SIG_INTEL = 0x756e6547, // Genu SIG_AMD = 0x68747541, // Auth @@ -69,6 +76,9 @@ enum ProcessorTypes { INTEL_GOLDMONT_PLUS, INTEL_TREMONT, AMDFAM19H, + ZHAOXIN_FAM7H, + INTEL_SIERRAFOREST, + INTEL_GRANDRIDGE, CPU_TYPE_MAX }; @@ -100,6 +110,9 @@ enum ProcessorSubtypes { INTEL_COREI7_ALDERLAKE, AMDFAM19H_ZNVER3, INTEL_COREI7_ROCKETLAKE, + ZHAOXIN_FAM7H_LUJIAZUI, + AMDFAM19H_ZNVER4, + INTEL_COREI7_GRANITERAPIDS, CPU_SUBTYPE_MAX }; @@ -149,7 +162,7 @@ enum ProcessorFeatures { // Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID // support. Consequently, for i386, the presence of CPUID is checked first // via the corresponding eflags bit. -static bool isCpuIdSupported() { +static bool isCpuIdSupported(void) { #if defined(__GNUC__) || defined(__clang__) #if defined(__i386__) int __cpuid_supported; @@ -422,6 +435,27 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, *Subtype = INTEL_COREI7_ICELAKE_CLIENT; break; + // Tigerlake: + case 0x8c: + case 0x8d: + CPU = "tigerlake"; + *Type = INTEL_COREI7; + *Subtype = INTEL_COREI7_TIGERLAKE; + break; + + // Alderlake: + case 0x97: + case 0x9a: + // Raptorlake: + case 0xb7: + // Meteorlake: + case 0xaa: + case 0xac: + CPU = "alderlake"; + *Type = INTEL_COREI7; + *Subtype = INTEL_COREI7_ALDERLAKE; + break; + // Icelake Xeon: case 0x6a: case 0x6c: @@ -430,6 +464,8 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, *Subtype = INTEL_COREI7_ICELAKE_SERVER; break; + // Emerald Rapids: + case 0xcf: // Sapphire Rapids: case 0x8f: CPU = "sapphirerapids"; @@ -437,6 +473,14 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, *Subtype = INTEL_COREI7_SAPPHIRERAPIDS; break; + // Granite Rapids: + case 0xae: + case 0xad: + CPU = "graniterapids"; + *Type = INTEL_COREI7; + *Subtype = INTEL_COREI7_GRANITERAPIDS; + break; + case 0x1c: // Most 45 nm Intel Atom processors case 0x26: // 45 nm Atom Lincroft case 0x27: // 32 nm Atom Medfield @@ -471,6 +515,18 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, *Type = INTEL_TREMONT; break; + // Sierraforest: + case 0xaf: + CPU = "sierraforest"; + *Type = INTEL_SIERRAFOREST; + break; + + // Grandridge: + case 0xb6: + CPU = "grandridge"; + *Type = INTEL_GRANDRIDGE; + break; + case 0x57: CPU = "knl"; *Type = INTEL_KNL; @@ -563,9 +619,22 @@ getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model, case 25: CPU = "znver3"; *Type = AMDFAM19H; - if (Model <= 0x0f) { + if (Model <= 0x0f || (Model >= 0x20 && Model <= 0x5f)) { + // Family 19h Models 00h-0Fh - Zen3 + // Family 19h Models 20h-2Fh - Zen3 + // Family 19h Models 30h-3Fh - Zen3 + // Family 19h Models 40h-4Fh - Zen3+ + // Family 19h Models 50h-5Fh - Zen3+ *Subtype = AMDFAM19H_ZNVER3; - break; // 00h-0Fh: Zen3 + break; + } + if ((Model >= 0x10 && Model <= 0x1f) || + (Model >= 0x60 && Model <= 0x74) || + (Model >= 0x78 && Model <= 0x7b) || + (Model >= 0xA0 && Model <= 0xAf)) { + CPU = "znver4"; + *Subtype = AMDFAM19H_ZNVER4; + break; // "znver4" } break; default: @@ -769,23 +838,520 @@ int CONSTRUCTOR_ATTRIBUTE __cpu_indicator_init(void) { return 0; } #elif defined(__aarch64__) + +#ifndef AT_HWCAP +#define AT_HWCAP 16 +#endif +#ifndef HWCAP_CPUID +#define HWCAP_CPUID (1 << 11) +#endif +#ifndef HWCAP_FP +#define HWCAP_FP (1 << 0) +#endif +#ifndef HWCAP_ASIMD +#define HWCAP_ASIMD (1 << 1) +#endif +#ifndef HWCAP_AES +#define HWCAP_AES (1 << 3) +#endif +#ifndef HWCAP_PMULL +#define HWCAP_PMULL (1 << 4) +#endif +#ifndef HWCAP_SHA1 +#define HWCAP_SHA1 (1 << 5) +#endif +#ifndef HWCAP_SHA2 +#define HWCAP_SHA2 (1 << 6) +#endif +#ifndef HWCAP_ATOMICS +#define HWCAP_ATOMICS (1 << 8) +#endif +#ifndef HWCAP_FPHP +#define HWCAP_FPHP (1 << 9) +#endif +#ifndef HWCAP_ASIMDHP +#define HWCAP_ASIMDHP (1 << 10) +#endif +#ifndef HWCAP_ASIMDRDM +#define HWCAP_ASIMDRDM (1 << 12) +#endif +#ifndef HWCAP_JSCVT +#define HWCAP_JSCVT (1 << 13) +#endif +#ifndef HWCAP_FCMA +#define HWCAP_FCMA (1 << 14) +#endif +#ifndef HWCAP_LRCPC +#define HWCAP_LRCPC (1 << 15) +#endif +#ifndef HWCAP_DCPOP +#define HWCAP_DCPOP (1 << 16) +#endif +#ifndef HWCAP_SHA3 +#define HWCAP_SHA3 (1 << 17) +#endif +#ifndef HWCAP_SM3 +#define HWCAP_SM3 (1 << 18) +#endif +#ifndef HWCAP_SM4 +#define HWCAP_SM4 (1 << 19) +#endif +#ifndef HWCAP_ASIMDDP +#define HWCAP_ASIMDDP (1 << 20) +#endif +#ifndef HWCAP_SHA512 +#define HWCAP_SHA512 (1 << 21) +#endif +#ifndef HWCAP_SVE +#define HWCAP_SVE (1 << 22) +#endif +#ifndef HWCAP_ASIMDFHM +#define HWCAP_ASIMDFHM (1 << 23) +#endif +#ifndef HWCAP_DIT +#define HWCAP_DIT (1 << 24) +#endif +#ifndef HWCAP_ILRCPC +#define HWCAP_ILRCPC (1 << 26) +#endif +#ifndef HWCAP_FLAGM +#define HWCAP_FLAGM (1 << 27) +#endif +#ifndef HWCAP_SSBS +#define HWCAP_SSBS (1 << 28) +#endif +#ifndef HWCAP_SB +#define HWCAP_SB (1 << 29) +#endif + +#ifndef AT_HWCAP2 +#define AT_HWCAP2 26 +#endif +#ifndef HWCAP2_DCPODP +#define HWCAP2_DCPODP (1 << 0) +#endif +#ifndef HWCAP2_SVE2 +#define HWCAP2_SVE2 (1 << 1) +#endif +#ifndef HWCAP2_SVEAES +#define HWCAP2_SVEAES (1 << 2) +#endif +#ifndef HWCAP2_SVEPMULL +#define HWCAP2_SVEPMULL (1 << 3) +#endif +#ifndef HWCAP2_SVEBITPERM +#define HWCAP2_SVEBITPERM (1 << 4) +#endif +#ifndef HWCAP2_SVESHA3 +#define HWCAP2_SVESHA3 (1 << 5) +#endif +#ifndef HWCAP2_SVESM4 +#define HWCAP2_SVESM4 (1 << 6) +#endif +#ifndef HWCAP2_FLAGM2 +#define HWCAP2_FLAGM2 (1 << 7) +#endif +#ifndef HWCAP2_FRINT +#define HWCAP2_FRINT (1 << 8) +#endif +#ifndef HWCAP2_SVEI8MM +#define HWCAP2_SVEI8MM (1 << 9) +#endif +#ifndef HWCAP2_SVEF32MM +#define HWCAP2_SVEF32MM (1 << 10) +#endif +#ifndef HWCAP2_SVEF64MM +#define HWCAP2_SVEF64MM (1 << 11) +#endif +#ifndef HWCAP2_SVEBF16 +#define HWCAP2_SVEBF16 (1 << 12) +#endif +#ifndef HWCAP2_I8MM +#define HWCAP2_I8MM (1 << 13) +#endif +#ifndef HWCAP2_BF16 +#define HWCAP2_BF16 (1 << 14) +#endif +#ifndef HWCAP2_DGH +#define HWCAP2_DGH (1 << 15) +#endif +#ifndef HWCAP2_RNG +#define HWCAP2_RNG (1 << 16) +#endif +#ifndef HWCAP2_BTI +#define HWCAP2_BTI (1 << 17) +#endif +#ifndef HWCAP2_MTE +#define HWCAP2_MTE (1 << 18) +#endif +#ifndef HWCAP2_RPRES +#define HWCAP2_RPRES (1 << 21) +#endif +#ifndef HWCAP2_MTE3 +#define HWCAP2_MTE3 (1 << 22) +#endif +#ifndef HWCAP2_SME +#define HWCAP2_SME (1 << 23) +#endif +#ifndef HWCAP2_SME_I16I64 +#define HWCAP2_SME_I16I64 (1 << 24) +#endif +#ifndef HWCAP2_SME_F64F64 +#define HWCAP2_SME_F64F64 (1 << 25) +#endif +#ifndef HWCAP2_WFXT +#define HWCAP2_WFXT (1UL << 31) +#endif +#ifndef HWCAP2_EBF16 +#define HWCAP2_EBF16 (1UL << 32) +#endif +#ifndef HWCAP2_SVE_EBF16 +#define HWCAP2_SVE_EBF16 (1UL << 33) +#endif + // LSE support detection for out-of-line atomics // using HWCAP and Auxiliary vector _Bool __aarch64_have_lse_atomics __attribute__((visibility("hidden"), nocommon)); + #if defined(__has_include) #if __has_include() #include -#ifndef AT_HWCAP -#define AT_HWCAP 16 -#endif -#ifndef HWCAP_ATOMICS -#define HWCAP_ATOMICS (1 << 8) +#if __has_include() +#include + +#if defined(__ANDROID__) +#include +#include +#elif defined(__Fuchsia__) +#include +#include #endif + +// Detect Exynos 9810 CPU +#define IF_EXYNOS9810 \ + char arch[PROP_VALUE_MAX]; \ + if (__system_property_get("ro.arch", arch) > 0 && \ + strncmp(arch, "exynos9810", sizeof("exynos9810") - 1) == 0) + static void CONSTRUCTOR_ATTRIBUTE init_have_lse_atomics(void) { +#if defined(__FreeBSD__) + unsigned long hwcap; + int result = elf_aux_info(AT_HWCAP, &hwcap, sizeof hwcap); + __aarch64_have_lse_atomics = result == 0 && (hwcap & HWCAP_ATOMICS) != 0; +#elif defined(__Fuchsia__) + // This ensures the vDSO is a direct link-time dependency of anything that + // needs this initializer code. +#pragma comment(lib, "zircon") + uint32_t features; + zx_status_t status = _zx_system_get_features(ZX_FEATURE_KIND_CPU, &features); + __aarch64_have_lse_atomics = + status == ZX_OK && (features & ZX_ARM64_FEATURE_ISA_ATOMICS) != 0; +#else unsigned long hwcap = getauxval(AT_HWCAP); - __aarch64_have_lse_atomics = (hwcap & HWCAP_ATOMICS) != 0; + _Bool result = (hwcap & HWCAP_ATOMICS) != 0; +#if defined(__ANDROID__) + if (result) { + // Some cores in the Exynos 9810 CPU are ARMv8.2 and others are ARMv8.0; + // only the former support LSE atomics. However, the kernel in the + // initial Android 8.0 release of Galaxy S9/S9+ devices incorrectly + // reported the feature as being supported. + // + // The kernel appears to have been corrected to mark it unsupported as of + // the Android 9.0 release on those devices, and this issue has not been + // observed anywhere else. Thus, this workaround may be removed if + // compiler-rt ever drops support for Android 8.0. + IF_EXYNOS9810 result = false; + } +#endif // defined(__ANDROID__) + __aarch64_have_lse_atomics = result; +#endif // defined(__FreeBSD__) +} + +#if !defined(DISABLE_AARCH64_FMV) +// CPUFeatures must correspond to the same AArch64 features in +// AArch64TargetParser.h +enum CPUFeatures { + FEAT_RNG, + FEAT_FLAGM, + FEAT_FLAGM2, + FEAT_FP16FML, + FEAT_DOTPROD, + FEAT_SM4, + FEAT_RDM, + FEAT_LSE, + FEAT_FP, + FEAT_SIMD, + FEAT_CRC, + FEAT_SHA1, + FEAT_SHA2, + FEAT_SHA3, + FEAT_AES, + FEAT_PMULL, + FEAT_FP16, + FEAT_DIT, + FEAT_DPB, + FEAT_DPB2, + FEAT_JSCVT, + FEAT_FCMA, + FEAT_RCPC, + FEAT_RCPC2, + FEAT_FRINTTS, + FEAT_DGH, + FEAT_I8MM, + FEAT_BF16, + FEAT_EBF16, + FEAT_RPRES, + FEAT_SVE, + FEAT_SVE_BF16, + FEAT_SVE_EBF16, + FEAT_SVE_I8MM, + FEAT_SVE_F32MM, + FEAT_SVE_F64MM, + FEAT_SVE2, + FEAT_SVE_AES, + FEAT_SVE_PMULL128, + FEAT_SVE_BITPERM, + FEAT_SVE_SHA3, + FEAT_SVE_SM4, + FEAT_SME, + FEAT_MEMTAG, + FEAT_MEMTAG2, + FEAT_MEMTAG3, + FEAT_SB, + FEAT_PREDRES, + FEAT_SSBS, + FEAT_SSBS2, + FEAT_BTI, + FEAT_LS64, + FEAT_LS64_V, + FEAT_LS64_ACCDATA, + FEAT_WFXT, + FEAT_SME_F64, + FEAT_SME_I64, + FEAT_SME2, + FEAT_MAX +}; + +// Architecture features used +// in Function Multi Versioning +struct { + unsigned long long features; + // As features grows new fields could be added +} __aarch64_cpu_features __attribute__((visibility("hidden"), nocommon)); + +void init_cpu_features_resolver(unsigned long hwcap, unsigned long hwcap2) { +#define setCPUFeature(F) __aarch64_cpu_features.features |= 1ULL << F +#define getCPUFeature(id, ftr) __asm__("mrs %0, " #id : "=r"(ftr)) +#define extractBits(val, start, number) \ + (val & ((1ULL << number) - 1ULL) << start) >> start + if (hwcap & HWCAP_CRC32) + setCPUFeature(FEAT_CRC); + if (hwcap & HWCAP_PMULL) + setCPUFeature(FEAT_PMULL); + if (hwcap & HWCAP_FLAGM) + setCPUFeature(FEAT_FLAGM); + if (hwcap2 & HWCAP2_FLAGM2) { + setCPUFeature(FEAT_FLAGM); + setCPUFeature(FEAT_FLAGM2); + } + if (hwcap & HWCAP_SM3 && hwcap & HWCAP_SM4) + setCPUFeature(FEAT_SM4); + if (hwcap & HWCAP_ASIMDDP) + setCPUFeature(FEAT_DOTPROD); + if (hwcap & HWCAP_ASIMDFHM) + setCPUFeature(FEAT_FP16FML); + if (hwcap & HWCAP_FPHP) { + setCPUFeature(FEAT_FP16); + setCPUFeature(FEAT_FP); + } + if (hwcap & HWCAP_DIT) + setCPUFeature(FEAT_DIT); + if (hwcap & HWCAP_ASIMDRDM) + setCPUFeature(FEAT_RDM); + if (hwcap & HWCAP_ILRCPC) + setCPUFeature(FEAT_RCPC2); + if (hwcap & HWCAP_AES) + setCPUFeature(FEAT_AES); + if (hwcap & HWCAP_SHA1) + setCPUFeature(FEAT_SHA1); + if (hwcap & HWCAP_SHA2) + setCPUFeature(FEAT_SHA2); + if (hwcap & HWCAP_JSCVT) + setCPUFeature(FEAT_JSCVT); + if (hwcap & HWCAP_FCMA) + setCPUFeature(FEAT_FCMA); + if (hwcap & HWCAP_SB) + setCPUFeature(FEAT_SB); + if (hwcap & HWCAP_SSBS) + setCPUFeature(FEAT_SSBS2); + if (hwcap2 & HWCAP2_MTE) { + setCPUFeature(FEAT_MEMTAG); + setCPUFeature(FEAT_MEMTAG2); + } + if (hwcap2 & HWCAP2_MTE3) { + setCPUFeature(FEAT_MEMTAG); + setCPUFeature(FEAT_MEMTAG2); + setCPUFeature(FEAT_MEMTAG3); + } + if (hwcap2 & HWCAP2_SVEAES) + setCPUFeature(FEAT_SVE_AES); + if (hwcap2 & HWCAP2_SVEPMULL) { + setCPUFeature(FEAT_SVE_AES); + setCPUFeature(FEAT_SVE_PMULL128); + } + if (hwcap2 & HWCAP2_SVEBITPERM) + setCPUFeature(FEAT_SVE_BITPERM); + if (hwcap2 & HWCAP2_SVESHA3) + setCPUFeature(FEAT_SVE_SHA3); + if (hwcap2 & HWCAP2_SVESM4) + setCPUFeature(FEAT_SVE_SM4); + if (hwcap2 & HWCAP2_DCPODP) + setCPUFeature(FEAT_DPB2); + if (hwcap & HWCAP_ATOMICS) + setCPUFeature(FEAT_LSE); + if (hwcap2 & HWCAP2_RNG) + setCPUFeature(FEAT_RNG); + if (hwcap2 & HWCAP2_I8MM) + setCPUFeature(FEAT_I8MM); + if (hwcap2 & HWCAP2_EBF16) + setCPUFeature(FEAT_EBF16); + if (hwcap2 & HWCAP2_SVE_EBF16) + setCPUFeature(FEAT_SVE_EBF16); + if (hwcap2 & HWCAP2_DGH) + setCPUFeature(FEAT_DGH); + if (hwcap2 & HWCAP2_FRINT) + setCPUFeature(FEAT_FRINTTS); + if (hwcap2 & HWCAP2_SVEI8MM) + setCPUFeature(FEAT_SVE_I8MM); + if (hwcap2 & HWCAP2_SVEF32MM) + setCPUFeature(FEAT_SVE_F32MM); + if (hwcap2 & HWCAP2_SVEF64MM) + setCPUFeature(FEAT_SVE_F64MM); + if (hwcap2 & HWCAP2_BTI) + setCPUFeature(FEAT_BTI); + if (hwcap2 & HWCAP2_RPRES) + setCPUFeature(FEAT_RPRES); + if (hwcap2 & HWCAP2_WFXT) + setCPUFeature(FEAT_WFXT); + if (hwcap2 & HWCAP2_SME) + setCPUFeature(FEAT_SME); + if (hwcap2 & HWCAP2_SME_I16I64) + setCPUFeature(FEAT_SME_I64); + if (hwcap2 & HWCAP2_SME_F64F64) + setCPUFeature(FEAT_SME_F64); + if (hwcap & HWCAP_CPUID) { + unsigned long ftr; + getCPUFeature(ID_AA64PFR1_EL1, ftr); + // ID_AA64PFR1_EL1.MTE >= 0b0001 + if (extractBits(ftr, 8, 4) >= 0x1) + setCPUFeature(FEAT_MEMTAG); + // ID_AA64PFR1_EL1.SSBS == 0b0001 + if (extractBits(ftr, 4, 4) == 0x1) + setCPUFeature(FEAT_SSBS); + // ID_AA64PFR1_EL1.SME == 0b0010 + if (extractBits(ftr, 24, 4) == 0x2) + setCPUFeature(FEAT_SME2); + getCPUFeature(ID_AA64PFR0_EL1, ftr); + // ID_AA64PFR0_EL1.FP != 0b1111 + if (extractBits(ftr, 16, 4) != 0xF) { + setCPUFeature(FEAT_FP); + // ID_AA64PFR0_EL1.AdvSIMD has the same value as ID_AA64PFR0_EL1.FP + setCPUFeature(FEAT_SIMD); + } + // ID_AA64PFR0_EL1.SVE != 0b0000 + if (extractBits(ftr, 32, 4) != 0x0) { + // get ID_AA64ZFR0_EL1, that name supported + // if sve enabled only + getCPUFeature(S3_0_C0_C4_4, ftr); + // ID_AA64ZFR0_EL1.SVEver == 0b0000 + if (extractBits(ftr, 0, 4) == 0x0) + setCPUFeature(FEAT_SVE); + // ID_AA64ZFR0_EL1.SVEver == 0b0001 + if (extractBits(ftr, 0, 4) == 0x1) + setCPUFeature(FEAT_SVE2); + // ID_AA64ZFR0_EL1.BF16 != 0b0000 + if (extractBits(ftr, 20, 4) != 0x0) + setCPUFeature(FEAT_SVE_BF16); + } + getCPUFeature(ID_AA64ISAR0_EL1, ftr); + // ID_AA64ISAR0_EL1.SHA3 != 0b0000 + if (extractBits(ftr, 32, 4) != 0x0) + setCPUFeature(FEAT_SHA3); + getCPUFeature(ID_AA64ISAR1_EL1, ftr); + // ID_AA64ISAR1_EL1.DPB >= 0b0001 + if (extractBits(ftr, 0, 4) >= 0x1) + setCPUFeature(FEAT_DPB); + // ID_AA64ISAR1_EL1.LRCPC != 0b0000 + if (extractBits(ftr, 20, 4) != 0x0) + setCPUFeature(FEAT_RCPC); + // ID_AA64ISAR1_EL1.SPECRES == 0b0001 + if (extractBits(ftr, 40, 4) == 0x2) + setCPUFeature(FEAT_PREDRES); + // ID_AA64ISAR1_EL1.BF16 != 0b0000 + if (extractBits(ftr, 44, 4) != 0x0) + setCPUFeature(FEAT_BF16); + // ID_AA64ISAR1_EL1.LS64 >= 0b0001 + if (extractBits(ftr, 60, 4) >= 0x1) + setCPUFeature(FEAT_LS64); + // ID_AA64ISAR1_EL1.LS64 >= 0b0010 + if (extractBits(ftr, 60, 4) >= 0x2) + setCPUFeature(FEAT_LS64_V); + // ID_AA64ISAR1_EL1.LS64 >= 0b0011 + if (extractBits(ftr, 60, 4) >= 0x3) + setCPUFeature(FEAT_LS64_ACCDATA); + } else { + // Set some features in case of no CPUID support + if (hwcap & (HWCAP_FP | HWCAP_FPHP)) { + setCPUFeature(FEAT_FP); + // FP and AdvSIMD fields have the same value + setCPUFeature(FEAT_SIMD); + } + if (hwcap & HWCAP_DCPOP || hwcap2 & HWCAP2_DCPODP) + setCPUFeature(FEAT_DPB); + if (hwcap & HWCAP_LRCPC || hwcap & HWCAP_ILRCPC) + setCPUFeature(FEAT_RCPC); + if (hwcap2 & HWCAP2_BF16 || hwcap2 & HWCAP2_EBF16) + setCPUFeature(FEAT_BF16); + if (hwcap2 & HWCAP2_SVEBF16) + setCPUFeature(FEAT_SVE_BF16); + if (hwcap2 & HWCAP2_SVE2 && hwcap & HWCAP_SVE) + setCPUFeature(FEAT_SVE2); + if (hwcap & HWCAP_SHA3) + setCPUFeature(FEAT_SHA3); + } +} + +void CONSTRUCTOR_ATTRIBUTE init_cpu_features(void) { + unsigned long hwcap; + unsigned long hwcap2; + // CPU features already initialized. + if (__aarch64_cpu_features.features) + return; + setCPUFeature(FEAT_MAX); +#if defined(__FreeBSD__) + int res = 0; + res = elf_aux_info(AT_HWCAP, &hwcap, sizeof hwcap); + res |= elf_aux_info(AT_HWCAP2, &hwcap2, sizeof hwcap2); + if (res) + return; +#else +#if defined(__ANDROID__) + // Don't set any CPU features, + // detection could be wrong on Exynos 9810. + IF_EXYNOS9810 return; +#endif // defined(__ANDROID__) + hwcap = getauxval(AT_HWCAP); + hwcap2 = getauxval(AT_HWCAP2); +#endif // defined(__FreeBSD__) + init_cpu_features_resolver(hwcap, hwcap2); +#undef extractBits +#undef getCPUFeature +#undef setCPUFeature +#undef IF_EXYNOS9810 } +#endif // !defined(DISABLE_AARCH64_FMV) #endif // defined(__has_include) #endif // __has_include() +#endif // __has_include() #endif // defined(__aarch64__) diff --git a/gnu/llvm/compiler-rt/lib/builtins/eprintf.c b/gnu/llvm/compiler-rt/lib/builtins/eprintf.c index 89fb0e315b2..daf90b4993e 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/eprintf.c +++ b/gnu/llvm/compiler-rt/lib/builtins/eprintf.c @@ -15,6 +15,7 @@ // // It should never be exported from a dylib, so it is marked // visibility hidden. +#ifndef DONT_DEFINE_EPRINTF #ifndef _WIN32 __attribute__((visibility("hidden"))) #endif @@ -25,3 +26,4 @@ __eprintf(const char *format, const char *assertion_expression, fflush(stderr); compilerrt_abort(); } +#endif diff --git a/gnu/llvm/compiler-rt/lib/builtins/fixdfdi.c b/gnu/llvm/compiler-rt/lib/builtins/fixdfdi.c index 511568fc12f..a48facb6859 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/fixdfdi.c +++ b/gnu/llvm/compiler-rt/lib/builtins/fixdfdi.c @@ -42,3 +42,7 @@ AEABI_RTABI di_int __aeabi_d2lz(fp_t a) { return __fixdfdi(a); } COMPILER_RT_ALIAS(__fixdfdi, __aeabi_d2lz) #endif #endif + +#if defined(__MINGW32__) && defined(__arm__) +COMPILER_RT_ALIAS(__fixdfdi, __dtoi64) +#endif diff --git a/gnu/llvm/compiler-rt/lib/builtins/fixsfdi.c b/gnu/llvm/compiler-rt/lib/builtins/fixsfdi.c index 0cf71c30311..3a66fb9e2f0 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/fixsfdi.c +++ b/gnu/llvm/compiler-rt/lib/builtins/fixsfdi.c @@ -42,3 +42,7 @@ AEABI_RTABI di_int __aeabi_f2lz(fp_t a) { return __fixsfdi(a); } COMPILER_RT_ALIAS(__fixsfdi, __aeabi_f2lz) #endif #endif + +#if defined(__MINGW32__) && defined(__arm__) +COMPILER_RT_ALIAS(__fixsfdi, __stoi64) +#endif diff --git a/gnu/llvm/compiler-rt/lib/builtins/fixunsdfdi.c b/gnu/llvm/compiler-rt/lib/builtins/fixunsdfdi.c index ccb256d2c7e..f15f86788e8 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/fixunsdfdi.c +++ b/gnu/llvm/compiler-rt/lib/builtins/fixunsdfdi.c @@ -40,3 +40,7 @@ AEABI_RTABI du_int __aeabi_d2ulz(fp_t a) { return __fixunsdfdi(a); } COMPILER_RT_ALIAS(__fixunsdfdi, __aeabi_d2ulz) #endif #endif + +#if defined(__MINGW32__) && defined(__arm__) +COMPILER_RT_ALIAS(__fixunsdfdi, __dtou64) +#endif diff --git a/gnu/llvm/compiler-rt/lib/builtins/fixunssfdi.c b/gnu/llvm/compiler-rt/lib/builtins/fixunssfdi.c index 647185fbabf..e8f600df976 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/fixunssfdi.c +++ b/gnu/llvm/compiler-rt/lib/builtins/fixunssfdi.c @@ -41,3 +41,7 @@ AEABI_RTABI du_int __aeabi_f2ulz(fp_t a) { return __fixunssfdi(a); } COMPILER_RT_ALIAS(__fixunssfdi, __aeabi_f2ulz) #endif #endif + +#if defined(__MINGW32__) && defined(__arm__) +COMPILER_RT_ALIAS(__fixunssfdi, __stou64) +#endif diff --git a/gnu/llvm/compiler-rt/lib/builtins/fixunsxfdi.c b/gnu/llvm/compiler-rt/lib/builtins/fixunsxfdi.c index 097a4e55e93..c8a8061b2cf 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/fixunsxfdi.c +++ b/gnu/llvm/compiler-rt/lib/builtins/fixunsxfdi.c @@ -26,7 +26,7 @@ // mmmm mmmm mmmm #if defined(_MSC_VER) && !defined(__clang__) -// MSVC throws a warning about 'unitialized variable use' here, +// MSVC throws a warning about 'uninitialized variable use' here, // disable it for builds that warn-as-error #pragma warning(push) #pragma warning(disable : 4700) diff --git a/gnu/llvm/compiler-rt/lib/builtins/fixunsxfsi.c b/gnu/llvm/compiler-rt/lib/builtins/fixunsxfsi.c index 3bc1288d38a..154abcbd35e 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/fixunsxfsi.c +++ b/gnu/llvm/compiler-rt/lib/builtins/fixunsxfsi.c @@ -26,7 +26,7 @@ // mmmm mmmm mmmm #if defined(_MSC_VER) && !defined(__clang__) -// MSVC throws a warning about 'unitialized variable use' here, +// MSVC throws a warning about 'uninitialized variable use' here, // disable it for builds that warn-as-error #pragma warning(push) #pragma warning(disable : 4700) diff --git a/gnu/llvm/compiler-rt/lib/builtins/fixxfdi.c b/gnu/llvm/compiler-rt/lib/builtins/fixxfdi.c index a7a0464feb9..86cf3767b75 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/fixxfdi.c +++ b/gnu/llvm/compiler-rt/lib/builtins/fixxfdi.c @@ -25,7 +25,7 @@ // mmmm mmmm mmmm #if defined(_MSC_VER) && !defined(__clang__) -// MSVC throws a warning about 'unitialized variable use' here, +// MSVC throws a warning about 'uninitialized variable use' here, // disable it for builds that warn-as-error #pragma warning(push) #pragma warning(disable : 4700) diff --git a/gnu/llvm/compiler-rt/lib/builtins/floatdidf.c b/gnu/llvm/compiler-rt/lib/builtins/floatdidf.c index 7ecb30bca71..d37c43b1f2f 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/floatdidf.c +++ b/gnu/llvm/compiler-rt/lib/builtins/floatdidf.c @@ -101,3 +101,7 @@ AEABI_RTABI double __aeabi_l2d(di_int a) { return __floatdidf(a); } COMPILER_RT_ALIAS(__floatdidf, __aeabi_l2d) #endif #endif + +#if defined(__MINGW32__) && defined(__arm__) +COMPILER_RT_ALIAS(__floatdidf, __i64tod) +#endif diff --git a/gnu/llvm/compiler-rt/lib/builtins/floatdisf.c b/gnu/llvm/compiler-rt/lib/builtins/floatdisf.c index faaa1bcb3c8..5c6316431e3 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/floatdisf.c +++ b/gnu/llvm/compiler-rt/lib/builtins/floatdisf.c @@ -73,3 +73,7 @@ AEABI_RTABI float __aeabi_l2f(di_int a) { return __floatdisf(a); } COMPILER_RT_ALIAS(__floatdisf, __aeabi_l2f) #endif #endif + +#if defined(__MINGW32__) && defined(__arm__) +COMPILER_RT_ALIAS(__floatdisf, __i64tos) +#endif diff --git a/gnu/llvm/compiler-rt/lib/builtins/floatsisf.c b/gnu/llvm/compiler-rt/lib/builtins/floatsisf.c index fe060407755..c01f81e41e8 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/floatsisf.c +++ b/gnu/llvm/compiler-rt/lib/builtins/floatsisf.c @@ -17,7 +17,7 @@ #include "int_lib.h" -COMPILER_RT_ABI fp_t __floatsisf(int a) { +COMPILER_RT_ABI fp_t __floatsisf(si_int a) { const int aWidth = sizeof a * CHAR_BIT; @@ -33,7 +33,7 @@ COMPILER_RT_ABI fp_t __floatsisf(int a) { } // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - __builtin_clz(a); + const int exponent = (aWidth - 1) - clzsi(a); rep_t result; // Shift a into the significand field, rounding if it is a right-shift diff --git a/gnu/llvm/compiler-rt/lib/builtins/floatsitf.c b/gnu/llvm/compiler-rt/lib/builtins/floatsitf.c index f56063f368d..80a4ef08fb0 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/floatsitf.c +++ b/gnu/llvm/compiler-rt/lib/builtins/floatsitf.c @@ -16,7 +16,7 @@ #include "fp_lib.h" #if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) -COMPILER_RT_ABI fp_t __floatsitf(int a) { +COMPILER_RT_ABI fp_t __floatsitf(si_int a) { const int aWidth = sizeof a * CHAR_BIT; @@ -26,14 +26,14 @@ COMPILER_RT_ABI fp_t __floatsitf(int a) { // All other cases begin by extracting the sign and absolute value of a rep_t sign = 0; - unsigned aAbs = (unsigned)a; + su_int aAbs = (su_int)a; if (a < 0) { sign = signBit; - aAbs = ~(unsigned)a + 1U; + aAbs = ~(su_int)a + (su_int)1U; } // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - __builtin_clz(aAbs); + const int exponent = (aWidth - 1) - clzsi(aAbs); rep_t result; // Shift a into the significand field and clear the implicit bit. diff --git a/gnu/llvm/compiler-rt/lib/builtins/floatundidf.c b/gnu/llvm/compiler-rt/lib/builtins/floatundidf.c index e5e533042a3..2ec802cdc13 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/floatundidf.c +++ b/gnu/llvm/compiler-rt/lib/builtins/floatundidf.c @@ -104,3 +104,7 @@ AEABI_RTABI double __aeabi_ul2d(du_int a) { return __floatundidf(a); } COMPILER_RT_ALIAS(__floatundidf, __aeabi_ul2d) #endif #endif + +#if defined(__MINGW32__) && defined(__arm__) +COMPILER_RT_ALIAS(__floatundidf, __u64tod) +#endif diff --git a/gnu/llvm/compiler-rt/lib/builtins/floatundisf.c b/gnu/llvm/compiler-rt/lib/builtins/floatundisf.c index 00d61b0c631..2a4157dc5e4 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/floatundisf.c +++ b/gnu/llvm/compiler-rt/lib/builtins/floatundisf.c @@ -70,3 +70,7 @@ AEABI_RTABI float __aeabi_ul2f(du_int a) { return __floatundisf(a); } COMPILER_RT_ALIAS(__floatundisf, __aeabi_ul2f) #endif #endif + +#if defined(__MINGW32__) && defined(__arm__) +COMPILER_RT_ALIAS(__floatundisf, __u64tos) +#endif diff --git a/gnu/llvm/compiler-rt/lib/builtins/floatunsisf.c b/gnu/llvm/compiler-rt/lib/builtins/floatunsisf.c index 33a1b5ae2a6..ec062b5943e 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/floatunsisf.c +++ b/gnu/llvm/compiler-rt/lib/builtins/floatunsisf.c @@ -17,7 +17,7 @@ #include "int_lib.h" -COMPILER_RT_ABI fp_t __floatunsisf(unsigned int a) { +COMPILER_RT_ABI fp_t __floatunsisf(su_int a) { const int aWidth = sizeof a * CHAR_BIT; @@ -26,7 +26,7 @@ COMPILER_RT_ABI fp_t __floatunsisf(unsigned int a) { return fromRep(0); // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - __builtin_clz(a); + const int exponent = (aWidth - 1) - clzsi(a); rep_t result; // Shift a into the significand field, rounding if it is a right-shift diff --git a/gnu/llvm/compiler-rt/lib/builtins/floatunsitf.c b/gnu/llvm/compiler-rt/lib/builtins/floatunsitf.c index a4bf0f65fe1..7ba1fb6000d 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/floatunsitf.c +++ b/gnu/llvm/compiler-rt/lib/builtins/floatunsitf.c @@ -16,7 +16,7 @@ #include "fp_lib.h" #if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) -COMPILER_RT_ABI fp_t __floatunsitf(unsigned int a) { +COMPILER_RT_ABI fp_t __floatunsitf(su_int a) { const int aWidth = sizeof a * CHAR_BIT; @@ -25,7 +25,7 @@ COMPILER_RT_ABI fp_t __floatunsitf(unsigned int a) { return fromRep(0); // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - __builtin_clz(a); + const int exponent = (aWidth - 1) - clzsi(a); rep_t result; // Shift a into the significand field and clear the implicit bit. diff --git a/gnu/llvm/compiler-rt/lib/builtins/fp_compare_impl.inc b/gnu/llvm/compiler-rt/lib/builtins/fp_compare_impl.inc index 40fc7df4c67..a9a4f6fbf5d 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/fp_compare_impl.inc +++ b/gnu/llvm/compiler-rt/lib/builtins/fp_compare_impl.inc @@ -18,6 +18,9 @@ typedef int CMP_RESULT; #elif __SIZEOF_POINTER__ == 8 && __SIZEOF_LONG__ == 4 // LLP64 ABIs use long long instead of long. typedef long long CMP_RESULT; +#elif __AVR__ +// AVR uses a single byte for the return value. +typedef char CMP_RESULT; #else // Otherwise the comparison functions return long. typedef long CMP_RESULT; diff --git a/gnu/llvm/compiler-rt/lib/builtins/fp_extend.h b/gnu/llvm/compiler-rt/lib/builtins/fp_extend.h index aad4436730d..eee4722bf90 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/fp_extend.h +++ b/gnu/llvm/compiler-rt/lib/builtins/fp_extend.h @@ -33,9 +33,9 @@ static __inline int src_rep_t_clz(src_rep_t a) { return __builtin_clzl(a); #else if (a & REP_C(0xffffffff00000000)) - return __builtin_clz(a >> 32); + return clzsi(a >> 32); else - return 32 + __builtin_clz(a & REP_C(0xffffffff)); + return 32 + clzsi(a & REP_C(0xffffffff)); #endif } diff --git a/gnu/llvm/compiler-rt/lib/builtins/fp_mode.c b/gnu/llvm/compiler-rt/lib/builtins/fp_mode.c index b84df8abb27..51865473cda 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/fp_mode.c +++ b/gnu/llvm/compiler-rt/lib/builtins/fp_mode.c @@ -15,8 +15,8 @@ #include "fp_mode.h" // IEEE-754 default rounding (to nearest, ties to even). -CRT_FE_ROUND_MODE __fe_getround() { return CRT_FE_TONEAREST; } +CRT_FE_ROUND_MODE __fe_getround(void) { return CRT_FE_TONEAREST; } -int __fe_raise_inexact() { +int __fe_raise_inexact(void) { return 0; } diff --git a/gnu/llvm/compiler-rt/lib/builtins/fp_mode.h b/gnu/llvm/compiler-rt/lib/builtins/fp_mode.h index 26a3f4d1094..5b4969a441f 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/fp_mode.h +++ b/gnu/llvm/compiler-rt/lib/builtins/fp_mode.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef FP_MODE -#define FP_MODE +#ifndef FP_MODE_H +#define FP_MODE_H typedef enum { CRT_FE_TONEAREST, diff --git a/gnu/llvm/compiler-rt/lib/builtins/fp_trunc.h b/gnu/llvm/compiler-rt/lib/builtins/fp_trunc.h index 00595edd5e0..91f614528ab 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/fp_trunc.h +++ b/gnu/llvm/compiler-rt/lib/builtins/fp_trunc.h @@ -59,6 +59,12 @@ typedef uint16_t dst_rep_t; #define DST_REP_C UINT16_C static const int dstSigBits = 10; +#elif defined DST_BFLOAT +typedef __bf16 dst_t; +typedef uint16_t dst_rep_t; +#define DST_REP_C UINT16_C +static const int dstSigBits = 7; + #else #error Destination should be single precision or double precision! #endif // end destination precision diff --git a/gnu/llvm/compiler-rt/lib/builtins/gcc_personality_v0.c b/gnu/llvm/compiler-rt/lib/builtins/gcc_personality_v0.c index afb9e2e113d..58fd7ceb58c 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/gcc_personality_v0.c +++ b/gnu/llvm/compiler-rt/lib/builtins/gcc_personality_v0.c @@ -143,7 +143,7 @@ static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) { } #if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ - !defined(__ARM_DWARF_EH__) + !defined(__ARM_DWARF_EH__) && !defined(__SEH__) #define USING_ARM_EHABI 1 _Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception *, struct _Unwind_Context *); diff --git a/gnu/llvm/compiler-rt/lib/builtins/i386/fp_mode.c b/gnu/llvm/compiler-rt/lib/builtins/i386/fp_mode.c index 80e272e4c9a..887ca9c34c1 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/i386/fp_mode.c +++ b/gnu/llvm/compiler-rt/lib/builtins/i386/fp_mode.c @@ -14,7 +14,7 @@ #define X87_TOWARDZERO 0x0c00 #define X87_RMODE_MASK (X87_TONEAREST | X87_UPWARD | X87_DOWNWARD | X87_TOWARDZERO) -CRT_FE_ROUND_MODE __fe_getround() { +CRT_FE_ROUND_MODE __fe_getround(void) { // Assume that the rounding mode state for the fpu agrees with the SSE unit. unsigned short cw; __asm__ __volatile__ ("fnstcw %0" : "=m" (cw)); @@ -32,7 +32,7 @@ CRT_FE_ROUND_MODE __fe_getround() { return CRT_FE_TONEAREST; } -int __fe_raise_inexact() { +int __fe_raise_inexact(void) { float f = 1.0f, g = 3.0f; __asm__ __volatile__ ("fdivs %1" : "+t" (f) : "m" (g)); return 0; diff --git a/gnu/llvm/compiler-rt/lib/builtins/int_endianness.h b/gnu/llvm/compiler-rt/lib/builtins/int_endianness.h index def046c34a6..291c6b58c8e 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/int_endianness.h +++ b/gnu/llvm/compiler-rt/lib/builtins/int_endianness.h @@ -41,7 +41,7 @@ #error "unknown endianness" #endif // !_LITTLE_ENDIAN -#endif // Solaris and AuroraUX. +#endif // Solaris // .. diff --git a/gnu/llvm/compiler-rt/lib/builtins/int_types.h b/gnu/llvm/compiler-rt/lib/builtins/int_types.h index 7a72de48067..e94d3154c6d 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/int_types.h +++ b/gnu/llvm/compiler-rt/lib/builtins/int_types.h @@ -64,7 +64,7 @@ typedef union { } udwords; #if defined(__LP64__) || defined(__wasm__) || defined(__mips64) || \ - defined(__riscv) || defined(_WIN64) + defined(__SIZEOF_INT128__) || defined(_WIN64) #define CRT_HAS_128BIT #endif diff --git a/gnu/llvm/compiler-rt/lib/builtins/loongarch/fp_mode.c b/gnu/llvm/compiler-rt/lib/builtins/loongarch/fp_mode.c new file mode 100644 index 00000000000..31877fb02bd --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/builtins/loongarch/fp_mode.c @@ -0,0 +1,59 @@ +//=== lib/builtins/loongarch/fp_mode.c - Floaing-point mode utilities -*- C -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include "../fp_mode.h" + +#define LOONGARCH_TONEAREST 0x0000 +#define LOONGARCH_TOWARDZERO 0x0100 +#define LOONGARCH_UPWARD 0x0200 +#define LOONGARCH_DOWNWARD 0x0300 + +#define LOONGARCH_RMODE_MASK (LOONGARCH_TONEAREST | LOONGARCH_TOWARDZERO | \ + LOONGARCH_UPWARD | LOONGARCH_DOWNWARD) + +#define LOONGARCH_INEXACT 0x10000 + +CRT_FE_ROUND_MODE __fe_getround(void) { +#if __loongarch_frlen != 0 + int fcsr; +# ifdef __clang__ + __asm__ __volatile__("movfcsr2gr %0, $fcsr0" : "=r" (fcsr)); +# else + __asm__ __volatile__("movfcsr2gr %0, $r0" : "=r" (fcsr)); +# endif + fcsr &= LOONGARCH_RMODE_MASK; + switch (fcsr) { + case LOONGARCH_TOWARDZERO: + return CRT_FE_TOWARDZERO; + case LOONGARCH_DOWNWARD: + return CRT_FE_DOWNWARD; + case LOONGARCH_UPWARD: + return CRT_FE_UPWARD; + case LOONGARCH_TONEAREST: + default: + return CRT_FE_TONEAREST; + } +#else + return CRT_FE_TONEAREST; +#endif +} + +int __fe_raise_inexact(void) { +#if __loongarch_frlen != 0 + int fcsr; +# ifdef __clang__ + __asm__ __volatile__("movfcsr2gr %0, $fcsr0" : "=r" (fcsr)); + __asm__ __volatile__( + "movgr2fcsr $fcsr0, %0" :: "r" (fcsr | LOONGARCH_INEXACT)); +# else + __asm__ __volatile__("movfcsr2gr %0, $r0" : "=r" (fcsr)); + __asm__ __volatile__( + "movgr2fcsr $r0, %0" :: "r" (fcsr | LOONGARCH_INEXACT)); +# endif +#endif + return 0; +} diff --git a/gnu/llvm/compiler-rt/lib/builtins/macho_embedded/common.txt b/gnu/llvm/compiler-rt/lib/builtins/macho_embedded/common.txt index 6ac85a771fc..819109768f5 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/macho_embedded/common.txt +++ b/gnu/llvm/compiler-rt/lib/builtins/macho_embedded/common.txt @@ -90,3 +90,4 @@ atomic_flag_test_and_set_explicit atomic_signal_fence atomic_thread_fence int_util +fp_mode diff --git a/gnu/llvm/compiler-rt/lib/builtins/os_version_check.c b/gnu/llvm/compiler-rt/lib/builtins/os_version_check.c index d7194b99ae5..ebfb2dfc72d 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/os_version_check.c +++ b/gnu/llvm/compiler-rt/lib/builtins/os_version_check.c @@ -307,8 +307,8 @@ static void readSystemProperties(void) { } int32_t __isOSVersionAtLeast(int32_t Major, int32_t Minor, int32_t Subminor) { - (int32_t) Minor; - (int32_t) Subminor; + (void) Minor; + (void) Subminor; static pthread_once_t once = PTHREAD_ONCE_INIT; pthread_once(&once, readSystemProperties); diff --git a/gnu/llvm/compiler-rt/lib/builtins/riscv/fp_mode.c b/gnu/llvm/compiler-rt/lib/builtins/riscv/fp_mode.c new file mode 100644 index 00000000000..c542c34c9cc --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/builtins/riscv/fp_mode.c @@ -0,0 +1,42 @@ +//=== lib/builtins/riscv/fp_mode.c - Floaing-point mode utilities -*- C -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include "../fp_mode.h" + +#define RISCV_TONEAREST 0x0 +#define RISCV_TOWARDZERO 0x1 +#define RISCV_DOWNWARD 0x2 +#define RISCV_UPWARD 0x3 + +#define RISCV_INEXACT 0x1 + +CRT_FE_ROUND_MODE __fe_getround(void) { +#if defined(__riscv_f) + int frm; + __asm__ __volatile__("frrm %0" : "=r" (frm)); + switch (frm) { + case RISCV_TOWARDZERO: + return CRT_FE_TOWARDZERO; + case RISCV_DOWNWARD: + return CRT_FE_DOWNWARD; + case RISCV_UPWARD: + return CRT_FE_UPWARD; + case RISCV_TONEAREST: + default: + return CRT_FE_TONEAREST; + } +#else + return CRT_FE_TONEAREST; +#endif +} + +int __fe_raise_inexact(void) { +#if defined(__riscv_f) + __asm__ __volatile__("csrsi fflags, %0" :: "i" (RISCV_INEXACT)); +#endif + return 0; +} diff --git a/gnu/llvm/compiler-rt/lib/builtins/riscv/restore.S b/gnu/llvm/compiler-rt/lib/builtins/riscv/restore.S index 12f0d336565..73f64a920d6 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/riscv/restore.S +++ b/gnu/llvm/compiler-rt/lib/builtins/riscv/restore.S @@ -93,7 +93,7 @@ __riscv_restore_0: __riscv_restore_12: ld s11, 8(sp) addi sp, sp, 16 - // fallthrough into __riscv_restore_11/10/9/8 + // fallthrough into __riscv_restore_11/10 .globl __riscv_restore_11 .type __riscv_restore_11,@function @@ -143,10 +143,6 @@ __riscv_restore_4: .type __riscv_restore_3,@function .globl __riscv_restore_2 .type __riscv_restore_2,@function - .globl __riscv_restore_1 - .type __riscv_restore_1,@function - .globl __riscv_restore_0 - .type __riscv_restore_0,@function __riscv_restore_3: __riscv_restore_2: ld s2, 0(sp) @@ -154,6 +150,10 @@ __riscv_restore_2: addi sp, sp, 16 // fallthrough into __riscv_restore_1/0 + .globl __riscv_restore_1 + .type __riscv_restore_1,@function + .globl __riscv_restore_0 + .type __riscv_restore_0,@function __riscv_restore_1: __riscv_restore_0: ld s0, 0(sp) diff --git a/gnu/llvm/compiler-rt/lib/builtins/riscv/save.S b/gnu/llvm/compiler-rt/lib/builtins/riscv/save.S index d811bf584fc..85501aeb4c2 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/riscv/save.S +++ b/gnu/llvm/compiler-rt/lib/builtins/riscv/save.S @@ -174,6 +174,8 @@ __riscv_save_2: .type __riscv_save_1,@function .globl __riscv_save_0 .type __riscv_save_0,@function +__riscv_save_1: +__riscv_save_0: addi sp, sp, -16 sd s0, 0(sp) sd ra, 8(sp) diff --git a/gnu/llvm/compiler-rt/lib/builtins/trampoline_setup.c b/gnu/llvm/compiler-rt/lib/builtins/trampoline_setup.c index a62431723d7..844eb279441 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/trampoline_setup.c +++ b/gnu/llvm/compiler-rt/lib/builtins/trampoline_setup.c @@ -16,7 +16,7 @@ extern void __clear_cache(void *start, void *end); // which loads r11 with a pointer to the outer function's locals // and then jumps to the target nested function. -#if __ppc__ && !defined(__powerpc64__) +#if __powerpc__ && !defined(__powerpc64__) COMPILER_RT_ABI void __trampoline_setup(uint32_t *trampOnStack, int trampSizeAllocated, const void *realFunc, void *localsPtr) { @@ -40,4 +40,4 @@ COMPILER_RT_ABI void __trampoline_setup(uint32_t *trampOnStack, // clear instruction cache __clear_cache(trampOnStack, &trampOnStack[10]); } -#endif // __ppc__ && !defined(__powerpc64__) +#endif // __powerpc__ && !defined(__powerpc64__) diff --git a/gnu/llvm/compiler-rt/lib/builtins/truncdfbf2.c b/gnu/llvm/compiler-rt/lib/builtins/truncdfbf2.c new file mode 100644 index 00000000000..dbd54dcd50c --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/builtins/truncdfbf2.c @@ -0,0 +1,13 @@ +//===-- lib/truncdfbf2.c - double -> bfloat conversion ------------*- C -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#define SRC_DOUBLE +#define DST_BFLOAT +#include "fp_trunc_impl.inc" + +COMPILER_RT_ABI dst_t __truncdfbf2(double a) { return __truncXfYf2__(a); } diff --git a/gnu/llvm/compiler-rt/lib/builtins/truncsfbf2.c b/gnu/llvm/compiler-rt/lib/builtins/truncsfbf2.c new file mode 100644 index 00000000000..6bed116af98 --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/builtins/truncsfbf2.c @@ -0,0 +1,13 @@ +//===-- lib/truncsfbf2.c - single -> bfloat conversion ------------*- C -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#define SRC_SINGLE +#define DST_BFLOAT +#include "fp_trunc_impl.inc" + +COMPILER_RT_ABI dst_t __truncsfbf2(float a) { return __truncXfYf2__(a); } diff --git a/gnu/llvm/compiler-rt/lib/builtins/udivmoddi4.c b/gnu/llvm/compiler-rt/lib/builtins/udivmoddi4.c index 10b41df28f8..123e5fb05f8 100644 --- a/gnu/llvm/compiler-rt/lib/builtins/udivmoddi4.c +++ b/gnu/llvm/compiler-rt/lib/builtins/udivmoddi4.c @@ -21,7 +21,7 @@ // MSVC throws a warning about mod 0 here, disable it for builds that // warn-as-error #pragma warning(push) -#pragma warning(disable : 4724) +#pragma warning(disable : 4723 4724) #endif COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) { @@ -82,7 +82,7 @@ COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) { r.s.high = n.s.high & (d.s.high - 1); *rem = r.all; } - return n.s.high >> __builtin_ctz(d.s.high); + return n.s.high >> ctzsi(d.s.high); } // K K // --- @@ -112,7 +112,7 @@ COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) { *rem = n.s.low & (d.s.low - 1); if (d.s.low == 1) return n.all; - sr = __builtin_ctz(d.s.low); + sr = ctzsi(d.s.low); q.s.high = n.s.high >> sr; q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); return q.all; diff --git a/gnu/llvm/compiler-rt/lib/cfi/CMakeLists.txt b/gnu/llvm/compiler-rt/lib/cfi/CMakeLists.txt index cfd52377814..2197fa4a5c7 100644 --- a/gnu/llvm/compiler-rt/lib/cfi/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/lib/cfi/CMakeLists.txt @@ -11,6 +11,9 @@ if(OS_NAME MATCHES "Linux" OR OS_NAME MATCHES "FreeBSD" OR OS_NAME MATCHES "NetB ${SANITIZER_COMMON_CFLAGS} ) + # Too many existing bugs, needs cleanup. + append_list_if(COMPILER_RT_HAS_WNO_FORMAT -Wno-format CFI_CFLAGS) + set(CFI_DIAG_CFLAGS -DCFI_ENABLE_DIAG=1 ) diff --git a/gnu/llvm/compiler-rt/lib/cfi/cfi.cpp b/gnu/llvm/compiler-rt/lib/cfi/cfi.cpp index f691cfb94cf..22f0b175dd8 100644 --- a/gnu/llvm/compiler-rt/lib/cfi/cfi.cpp +++ b/gnu/llvm/compiler-rt/lib/cfi/cfi.cpp @@ -230,7 +230,7 @@ uptr find_cfi_check_in_dso(dl_phdr_info *info) { } if (symtab > strtab) { - VReport(1, "Can not handle: symtab > strtab (%p > %zx)\n", symtab, strtab); + VReport(1, "Can not handle: symtab > strtab (%zx > %zx)\n", symtab, strtab); return 0; } @@ -250,7 +250,7 @@ uptr find_cfi_check_in_dso(dl_phdr_info *info) { 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); + VReport(1, "Can not handle: symtab %zx, strtab %zx\n", symtab, strtab); return 0; } @@ -320,16 +320,16 @@ void InitShadow() { } THREADLOCAL int in_loader; -BlockingMutex shadow_update_lock(LINKER_INITIALIZED); +Mutex shadow_update_lock; -void EnterLoader() NO_THREAD_SAFETY_ANALYSIS { +void EnterLoader() SANITIZER_NO_THREAD_SAFETY_ANALYSIS { if (in_loader == 0) { shadow_update_lock.Lock(); } ++in_loader; } -void ExitLoader() NO_THREAD_SAFETY_ANALYSIS { +void ExitLoader() SANITIZER_NO_THREAD_SAFETY_ANALYSIS { CHECK(in_loader > 0); --in_loader; UpdateShadow(); @@ -359,7 +359,7 @@ ALWAYS_INLINE void CfiSlowPathCommon(u64 CallSiteTypeId, void *Ptr, return; } CFICheckFn cfi_check = sv.get_cfi_check(); - VReport(2, "__cfi_check at %p\n", cfi_check); + VReport(2, "__cfi_check at %p\n", (void *)cfi_check); cfi_check(CallSiteTypeId, Ptr, DiagData); } @@ -436,11 +436,11 @@ INTERCEPTOR(int, dlclose, void *handle) { return res; } -static BlockingMutex interceptor_init_lock(LINKER_INITIALIZED); +static Mutex interceptor_init_lock; static bool interceptors_inited = false; static void EnsureInterceptorsInitialized() { - BlockingMutexLock lock(&interceptor_init_lock); + Lock lock(&interceptor_init_lock); if (interceptors_inited) return; diff --git a/gnu/llvm/compiler-rt/lib/crt/CMakeLists.txt b/gnu/llvm/compiler-rt/lib/crt/CMakeLists.txt index 0f8689268b9..771652f438f 100644 --- a/gnu/llvm/compiler-rt/lib/crt/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/lib/crt/CMakeLists.txt @@ -1,114 +1,70 @@ -add_compiler_rt_component(crt) - -function(check_cxx_section_exists section output) - cmake_parse_arguments(ARG "" "" "SOURCE;FLAGS" ${ARGN}) - if(NOT ARG_SOURCE) - set(ARG_SOURCE "int main() { return 0; }\n") +if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + cmake_minimum_required(VERSION 3.13.4) + if ("${CMAKE_VERSION}" VERSION_LESS "3.20.0") + message(WARNING + "Your CMake version is ${CMAKE_VERSION}. Starting with LLVM 17.0.0, the " + "minimum version of CMake required to build LLVM will become 3.20.0, and " + "using an older CMake will become an error. Please upgrade your CMake to " + "at least 3.20.0 now to avoid issues in the future!") endif() - string(RANDOM TARGET_NAME) - set(TARGET_NAME "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cmTC_${TARGET_NAME}.dir") - file(MAKE_DIRECTORY ${TARGET_NAME}) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + project(CompilerRTCRT C) + set(COMPILER_RT_STANDALONE_BUILD TRUE) + set(COMPILER_RT_CRT_STANDALONE_BUILD TRUE) - file(WRITE "${TARGET_NAME}/CheckSectionExists.c" "${ARG_SOURCE}\n") + set(COMPILER_RT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..") - string(REGEX MATCHALL "<[A-Za-z0-9_]*>" substitutions - ${CMAKE_C_COMPILE_OBJECT}) + set(LLVM_COMMON_CMAKE_UTILS "${COMPILER_RT_SOURCE_DIR}/../cmake") - set(try_compile_flags "${ARG_FLAGS}") - if(CMAKE_C_COMPILER_ID MATCHES Clang AND CMAKE_C_COMPILER_TARGET) - list(APPEND try_compile_flags "-target ${CMAKE_C_COMPILER_TARGET}") - endif() - append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto try_compile_flags) - if(NOT COMPILER_RT_ENABLE_PGO) - if(LLVM_PROFDATA_FILE AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_USE_FLAG) - list(APPEND try_compile_flags "-fno-profile-instr-use") - endif() - if(LLVM_BUILD_INSTRUMENTED MATCHES IR AND COMPILER_RT_HAS_FNO_PROFILE_GENERATE_FLAG) - list(APPEND try_compile_flags "-fno-profile-generate") - elseif(LLVM_BUILD_INSTRUMENTED AND COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG) - list(APPEND try_compile_flags "-fno-profile-instr-generate") - endif() - endif() + # Add path for custom modules + list(INSERT CMAKE_MODULE_PATH 0 + "${COMPILER_RT_SOURCE_DIR}/cmake" + "${COMPILER_RT_SOURCE_DIR}/cmake/Modules" + "${LLVM_COMMON_CMAKE_UTILS}" + "${LLVM_COMMON_CMAKE_UTILS}/Modules" + ) - string(REPLACE ";" " " extra_flags "${try_compile_flags}") - - set(test_compile_command "${CMAKE_C_COMPILE_OBJECT}") - foreach(substitution ${substitutions}) - if(substitution STREQUAL "") - string(REPLACE "" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" - test_compile_command ${test_compile_command}) - elseif(substitution STREQUAL "") - string(REPLACE "" "${TARGET_NAME}/CheckSectionExists.o" - test_compile_command ${test_compile_command}) - elseif(substitution STREQUAL "") - string(REPLACE "" "${TARGET_NAME}/CheckSectionExists.c" - test_compile_command ${test_compile_command}) - elseif(substitution STREQUAL "") - string(REPLACE "" "${CMAKE_C_FLAGS} ${extra_flags}" - test_compile_command ${test_compile_command}) - else() - string(REPLACE "${substitution}" "" test_compile_command - ${test_compile_command}) - endif() - endforeach() + include(base-config-ix) + include(CompilerRTUtils) - # Strip quotes from the compile command, as the compiler is not expecting - # quoted arguments (potential quotes added from D62063). - string(REPLACE "\"" "" test_compile_command "${test_compile_command}") + load_llvm_config() + construct_compiler_rt_default_triple() - string(REPLACE " " ";" test_compile_command "${test_compile_command}") + include(SetPlatformToolchainTools) + include(AddCompilerRT) +endif() - execute_process( - COMMAND ${test_compile_command} - RESULT_VARIABLE TEST_RESULT - OUTPUT_VARIABLE TEST_OUTPUT - ERROR_VARIABLE TEST_ERROR - ) +include(crt-config-ix) - # Explicitly throw a fatal error message if test_compile_command fails. - if(TEST_RESULT) - message(FATAL_ERROR "${TEST_ERROR}") - return() - endif() +if(COMPILER_RT_HAS_CRT) + add_compiler_rt_component(crt) - execute_process( - COMMAND ${CMAKE_OBJDUMP} -h "${TARGET_NAME}/CheckSectionExists.o" - RESULT_VARIABLE CHECK_RESULT - OUTPUT_VARIABLE CHECK_OUTPUT - ERROR_VARIABLE CHECK_ERROR - ) - string(FIND "${CHECK_OUTPUT}" "${section}" SECTION_FOUND) + include(CheckSectionExists) + check_section_exists(".init_array" COMPILER_RT_HAS_INITFINI_ARRAY + SOURCE "volatile int x;\n__attribute__((constructor)) void f(void) {x = 0;}\nint main(void) { return 0; }\n") - if(NOT SECTION_FOUND EQUAL -1) - set(${output} TRUE PARENT_SCOPE) - else() - set(${output} FALSE PARENT_SCOPE) + append_list_if(COMPILER_RT_HAS_STD_C11_FLAG -std=c11 CRT_CFLAGS) + append_list_if(COMPILER_RT_HAS_INITFINI_ARRAY -DCRT_HAS_INITFINI_ARRAY CRT_CFLAGS) + append_list_if(COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY -DEH_USE_FRAME_REGISTRY CRT_CFLAGS) + append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC CRT_CFLAGS) + append_list_if(COMPILER_RT_HAS_WNO_PEDANTIC -Wno-pedantic CRT_CFLAGS) + if (COMPILER_RT_HAS_FCF_PROTECTION_FLAG) + append_list_if(COMPILER_RT_ENABLE_CET -fcf-protection=full CRT_CFLAGS) endif() - file(REMOVE_RECURSE ${TARGET_NAME}) -endfunction() - -check_cxx_section_exists(".init_array" COMPILER_RT_HAS_INITFINI_ARRAY - SOURCE "volatile int x;\n__attribute__((constructor)) void f() {x = 0;}\nint main() { return 0; }\n") - -append_list_if(COMPILER_RT_HAS_STD_C11_FLAG -std=c11 CRT_CFLAGS) -append_list_if(COMPILER_RT_HAS_INITFINI_ARRAY -DCRT_HAS_INITFINI_ARRAY CRT_CFLAGS) -append_list_if(COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY -DEH_USE_FRAME_REGISTRY CRT_CFLAGS) -append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC CRT_CFLAGS) -append_list_if(COMPILER_RT_HAS_WNO_PEDANTIC -Wno-pedantic CRT_CFLAGS) - -foreach(arch ${CRT_SUPPORTED_ARCH}) - add_compiler_rt_runtime(clang_rt.crtbegin - OBJECT - ARCHS ${arch} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtbegin.c - CFLAGS ${CRT_CFLAGS} - PARENT_TARGET crt) - add_compiler_rt_runtime(clang_rt.crtend - OBJECT - ARCHS ${arch} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtend.c - CFLAGS ${CRT_CFLAGS} - PARENT_TARGET crt) -endforeach() + foreach(arch ${CRT_SUPPORTED_ARCH}) + add_compiler_rt_runtime(clang_rt.crtbegin + OBJECT + ARCHS ${arch} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtbegin.c + CFLAGS ${CRT_CFLAGS} + PARENT_TARGET crt) + add_compiler_rt_runtime(clang_rt.crtend + OBJECT + ARCHS ${arch} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtend.c + CFLAGS ${CRT_CFLAGS} + PARENT_TARGET crt) + endforeach() +endif() diff --git a/gnu/llvm/compiler-rt/lib/crt/crtbegin.c b/gnu/llvm/compiler-rt/lib/crt/crtbegin.c index 481c158ac77..7b041ff00b6 100644 --- a/gnu/llvm/compiler-rt/lib/crt/crtbegin.c +++ b/gnu/llvm/compiler-rt/lib/crt/crtbegin.c @@ -28,7 +28,7 @@ extern fp __CTOR_LIST_END__[]; extern void __cxa_finalize(void *) __attribute__((weak)); -static void __attribute__((used)) __do_init() { +static void __attribute__((used)) __do_init(void) { static _Bool __initialized; if (__builtin_expect(__initialized, 0)) return; @@ -79,7 +79,7 @@ static fp __DTOR_LIST__[] extern fp __DTOR_LIST_END__[]; #endif -static void __attribute__((used)) __do_fini() { +static void __attribute__((used)) __do_fini(void) { static _Bool __finalized; if (__builtin_expect(__finalized, 0)) return; diff --git a/gnu/llvm/compiler-rt/lib/dfsan/CMakeLists.txt b/gnu/llvm/compiler-rt/lib/dfsan/CMakeLists.txt index 45cb9c97e2e..c5190584ac0 100644 --- a/gnu/llvm/compiler-rt/lib/dfsan/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/lib/dfsan/CMakeLists.txt @@ -26,6 +26,9 @@ append_rtti_flag(OFF DFSAN_COMMON_CFLAGS) # Prevent clang from generating libc calls. append_list_if(COMPILER_RT_HAS_FFREESTANDING_FLAG -ffreestanding DFSAN_COMMON_CFLAGS) +# Too many existing bugs, needs cleanup. +append_list_if(COMPILER_RT_HAS_WNO_FORMAT -Wno-format DFSAN_COMMON_CFLAGS) + # Static runtime library. add_compiler_rt_component(dfsan) diff --git a/gnu/llvm/compiler-rt/lib/dfsan/dfsan.cpp b/gnu/llvm/compiler-rt/lib/dfsan/dfsan.cpp index 6f9ae141d7a..faf5a6619c2 100644 --- a/gnu/llvm/compiler-rt/lib/dfsan/dfsan.cpp +++ b/gnu/llvm/compiler-rt/lib/dfsan/dfsan.cpp @@ -128,6 +128,17 @@ void __dfsan_unimplemented(char *fname) { fname); } +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_wrapper_extern_weak_null( + const void *addr, char *fname) { + if (!addr) + Report( + "ERROR: DataFlowSanitizer: dfsan generated wrapper calling null " + "extern_weak function %s\nIf this only happens with dfsan, the " + "dfsan instrumentation pass may be accidentally optimizing out a " + "null check\n", + fname); +} + // Use '-mllvm -dfsan-debug-nonzero-labels' and break on this function // to try to figure out where labels are being introduced in a nominally // label-free program. @@ -332,9 +343,9 @@ static void MoveOrigin(const void *dst, const void *src, uptr size, // origins by copying origins in a reverse order; otherwise, copy origins in // a normal order. The orders of origin transfer are consistent with the // orders of how memcpy and memmove transfer user data. - uptr src_aligned_beg = reinterpret_cast(src) & ~3UL; - uptr src_aligned_end = (reinterpret_cast(src) + size) & ~3UL; - uptr dst_aligned_beg = reinterpret_cast(dst) & ~3UL; + uptr src_aligned_beg = OriginAlignDown((uptr)src); + uptr src_aligned_end = OriginAlignDown((uptr)src + size); + uptr dst_aligned_beg = OriginAlignDown((uptr)dst); if (dst_aligned_beg < src_aligned_end && dst_aligned_beg >= src_aligned_beg) return ReverseCopyOrigin(dst, src, size, stack); return CopyOrigin(dst, src, size, stack); @@ -369,37 +380,6 @@ static void SetOrigin(const void *dst, uptr size, u32 origin) { *(u32 *)(end - kOriginAlign) = origin; } -static void WriteShadowInRange(dfsan_label label, uptr beg_shadow_addr, - uptr end_shadow_addr) { - // TODO: After changing dfsan_label to 8bit, use internal_memset when label - // is not 0. - dfsan_label *labelp = (dfsan_label *)beg_shadow_addr; - if (label) { - for (; (uptr)labelp < end_shadow_addr; ++labelp) *labelp = label; - return; - } - - for (; (uptr)labelp < end_shadow_addr; ++labelp) { - // Don't write the label if it is already the value we need it to be. - // In a program where most addresses are not labeled, it is common that - // a page of shadow memory is entirely zeroed. The Linux copy-on-write - // implementation will share all of the zeroed pages, making a copy of a - // page when any value is written. The un-sharing will happen even if - // the value written does not change the value in memory. Avoiding the - // write when both |label| and |*labelp| are zero dramatically reduces - // the amount of real memory used by large programs. - if (!*labelp) - continue; - - *labelp = 0; - } -} - -static void WriteShadowWithSize(dfsan_label label, uptr shadow_addr, - uptr size) { - WriteShadowInRange(label, shadow_addr, shadow_addr + size * sizeof(label)); -} - #define RET_CHAIN_ORIGIN(id) \ GET_CALLER_PC_BP_SP; \ (void)sp; \ @@ -432,12 +412,66 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_mem_origin_transfer( MoveOrigin(dst, src, len, &stack); } -SANITIZER_INTERFACE_ATTRIBUTE void dfsan_mem_origin_transfer(const void *dst, - const void *src, - uptr len) { +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_mem_origin_transfer( + const void *dst, const void *src, uptr len) { __dfsan_mem_origin_transfer(dst, src, len); } +static void CopyShadow(void *dst, const void *src, uptr len) { + internal_memcpy((void *)__dfsan::shadow_for(dst), + (const void *)__dfsan::shadow_for(src), + len * sizeof(dfsan_label)); +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_mem_shadow_transfer( + void *dst, const void *src, uptr len) { + CopyShadow(dst, src, len); +} + +// Copy shadow and origins of the len bytes from src to dst. +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void +__dfsan_mem_shadow_origin_transfer(void *dst, const void *src, uptr size) { + if (src == dst) + return; + CopyShadow(dst, src, size); + if (dfsan_get_track_origins()) { + // Duplicating code instead of calling __dfsan_mem_origin_transfer + // so that the getting the caller stack frame works correctly. + GET_CALLER_PC_BP; + GET_STORE_STACK_TRACE_PC_BP(pc, bp); + MoveOrigin(dst, src, size, &stack); + } +} + +// Copy shadow and origins as per __atomic_compare_exchange. +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void +__dfsan_mem_shadow_origin_conditional_exchange(u8 condition, void *target, + void *expected, + const void *desired, uptr size) { + void *dst; + const void *src; + // condition is result of native call to __atomic_compare_exchange + if (condition) { + // Copy desired into target + dst = target; + src = desired; + } else { + // Copy target into expected + dst = expected; + src = target; + } + if (src == dst) + return; + CopyShadow(dst, src, size); + if (dfsan_get_track_origins()) { + // Duplicating code instead of calling __dfsan_mem_origin_transfer + // so that the getting the caller stack frame works correctly. + GET_CALLER_PC_BP; + GET_STORE_STACK_TRACE_PC_BP(pc, bp); + MoveOrigin(dst, src, size, &stack); + } +} + namespace __dfsan { bool dfsan_inited = false; @@ -445,27 +479,11 @@ bool dfsan_init_is_running = false; void dfsan_copy_memory(void *dst, const void *src, uptr size) { internal_memcpy(dst, src, size); - internal_memcpy((void *)shadow_for(dst), (const void *)shadow_for(src), - size * sizeof(dfsan_label)); + dfsan_mem_shadow_transfer(dst, src, size); if (dfsan_get_track_origins()) dfsan_mem_origin_transfer(dst, src, size); } -} // namespace __dfsan - -// If the label s is tainted, set the size bytes from the address p to be a new -// origin chain with the previous ID o and the current stack trace. This is -// used by instrumentation to reduce code size when too much code is inserted. -extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_maybe_store_origin( - dfsan_label s, void *p, uptr size, dfsan_origin o) { - if (UNLIKELY(s)) { - GET_CALLER_PC_BP_SP; - (void)sp; - GET_STORE_STACK_TRACE_PC_BP(pc, bp); - SetOrigin(p, size, ChainOrigin(o, &stack)); - } -} - // Releases the pages within the origin address range. static void ReleaseOrigins(void *addr, uptr size) { const uptr beg_origin_addr = (uptr)__dfsan::origin_for(addr); @@ -484,6 +502,19 @@ static void ReleaseOrigins(void *addr, uptr size) { Die(); } +static void WriteZeroShadowInRange(uptr beg, uptr end) { + // Don't write the label if it is already the value we need it to be. + // In a program where most addresses are not labeled, it is common that + // a page of shadow memory is entirely zeroed. The Linux copy-on-write + // implementation will share all of the zeroed pages, making a copy of a + // page when any value is written. The un-sharing will happen even if + // the value written does not change the value in memory. Avoiding the + // write when both |label| and |*labelp| are zero dramatically reduces + // the amount of real memory used by large programs. + if (!mem_is_zero((const char *)beg, end - beg)) + internal_memset((void *)beg, 0, end - beg); +} + // Releases the pages within the shadow address range, and sets // the shadow addresses not on the pages to be 0. static void ReleaseOrClearShadows(void *addr, uptr size) { @@ -492,20 +523,22 @@ static void ReleaseOrClearShadows(void *addr, uptr size) { const uptr end_shadow_addr = (uptr)__dfsan::shadow_for(end_addr); if (end_shadow_addr - beg_shadow_addr < - common_flags()->clear_shadow_mmap_threshold) - return WriteShadowWithSize(0, beg_shadow_addr, size); + common_flags()->clear_shadow_mmap_threshold) { + WriteZeroShadowInRange(beg_shadow_addr, end_shadow_addr); + return; + } const uptr page_size = GetPageSizeCached(); const uptr beg_aligned = RoundUpTo(beg_shadow_addr, page_size); const uptr end_aligned = RoundDownTo(end_shadow_addr, page_size); if (beg_aligned >= end_aligned) { - WriteShadowWithSize(0, beg_shadow_addr, size); + WriteZeroShadowInRange(beg_shadow_addr, end_shadow_addr); } else { if (beg_aligned != beg_shadow_addr) - WriteShadowInRange(0, beg_shadow_addr, beg_aligned); + WriteZeroShadowInRange(beg_shadow_addr, beg_aligned); if (end_aligned != end_shadow_addr) - WriteShadowInRange(0, end_aligned, end_shadow_addr); + WriteZeroShadowInRange(end_aligned, end_shadow_addr); if (!MmapFixedSuperNoReserve(beg_aligned, end_aligned - beg_aligned)) Die(); } @@ -514,7 +547,7 @@ static void ReleaseOrClearShadows(void *addr, uptr size) { void SetShadow(dfsan_label label, void *addr, uptr size, dfsan_origin origin) { if (0 != label) { const uptr beg_shadow_addr = (uptr)__dfsan::shadow_for(addr); - WriteShadowWithSize(label, beg_shadow_addr, size); + internal_memset((void *)beg_shadow_addr, label, size); if (dfsan_get_track_origins()) SetOrigin(addr, size, origin); return; @@ -526,9 +559,24 @@ void SetShadow(dfsan_label label, void *addr, uptr size, dfsan_origin origin) { ReleaseOrClearShadows(addr, size); } +} // namespace __dfsan + +// If the label s is tainted, set the size bytes from the address p to be a new +// origin chain with the previous ID o and the current stack trace. This is +// used by instrumentation to reduce code size when too much code is inserted. +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_maybe_store_origin( + dfsan_label s, void *p, uptr size, dfsan_origin o) { + if (UNLIKELY(s)) { + GET_CALLER_PC_BP_SP; + (void)sp; + GET_STORE_STACK_TRACE_PC_BP(pc, bp); + SetOrigin(p, size, ChainOrigin(o, &stack)); + } +} + extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_set_label( dfsan_label label, dfsan_origin origin, void *addr, uptr size) { - SetShadow(label, addr, size, origin); + __dfsan::SetShadow(label, addr, size, origin); } SANITIZER_INTERFACE_ATTRIBUTE @@ -539,7 +587,7 @@ void dfsan_set_label(dfsan_label label, void *addr, uptr size) { GET_STORE_STACK_TRACE_PC_BP(pc, bp); init_origin = ChainOrigin(0, &stack, true); } - SetShadow(label, addr, size, init_origin); + __dfsan::SetShadow(label, addr, size, init_origin); } SANITIZER_INTERFACE_ATTRIBUTE @@ -616,6 +664,121 @@ dfsan_has_label(dfsan_label label, dfsan_label elem) { return (label & elem) == elem; } +namespace __dfsan { + +typedef void (*dfsan_conditional_callback_t)(dfsan_label label, + dfsan_origin origin); +static dfsan_conditional_callback_t conditional_callback = nullptr; +static dfsan_label labels_in_signal_conditional = 0; + +static void ConditionalCallback(dfsan_label label, dfsan_origin origin) { + // Programs have many branches. For efficiency the conditional sink callback + // handler needs to ignore as many as possible as early as possible. + if (label == 0) { + return; + } + if (conditional_callback == nullptr) { + return; + } + + // This initial ConditionalCallback handler needs to be in here in dfsan + // runtime (rather than being an entirely user implemented hook) so that it + // has access to dfsan thread information. + DFsanThread *t = GetCurrentThread(); + // A callback operation which does useful work (like record the flow) will + // likely be too long executed in a signal handler. + if (t && t->InSignalHandler()) { + // Record set of labels used in signal handler for completeness. + labels_in_signal_conditional |= label; + return; + } + + conditional_callback(label, origin); +} + +} // namespace __dfsan + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void +__dfsan_conditional_callback_origin(dfsan_label label, dfsan_origin origin) { + __dfsan::ConditionalCallback(label, origin); +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_conditional_callback( + dfsan_label label) { + __dfsan::ConditionalCallback(label, 0); +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_set_conditional_callback( + __dfsan::dfsan_conditional_callback_t callback) { + __dfsan::conditional_callback = callback; +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label +dfsan_get_labels_in_signal_conditional() { + return __dfsan::labels_in_signal_conditional; +} + +namespace __dfsan { + +typedef void (*dfsan_reaches_function_callback_t)(dfsan_label label, + dfsan_origin origin, + const char *file, + unsigned int line, + const char *function); +static dfsan_reaches_function_callback_t reaches_function_callback = nullptr; +static dfsan_label labels_in_signal_reaches_function = 0; + +static void ReachesFunctionCallback(dfsan_label label, dfsan_origin origin, + const char *file, unsigned int line, + const char *function) { + if (label == 0) { + return; + } + if (reaches_function_callback == nullptr) { + return; + } + + // This initial ReachesFunctionCallback handler needs to be in here in dfsan + // runtime (rather than being an entirely user implemented hook) so that it + // has access to dfsan thread information. + DFsanThread *t = GetCurrentThread(); + // A callback operation which does useful work (like record the flow) will + // likely be too long executed in a signal handler. + if (t && t->InSignalHandler()) { + // Record set of labels used in signal handler for completeness. + labels_in_signal_reaches_function |= label; + return; + } + + reaches_function_callback(label, origin, file, line, function); +} + +} // namespace __dfsan + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void +__dfsan_reaches_function_callback_origin(dfsan_label label, dfsan_origin origin, + const char *file, unsigned int line, + const char *function) { + __dfsan::ReachesFunctionCallback(label, origin, file, line, function); +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void +__dfsan_reaches_function_callback(dfsan_label label, const char *file, + unsigned int line, const char *function) { + __dfsan::ReachesFunctionCallback(label, 0, file, line, function); +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void +dfsan_set_reaches_function_callback( + __dfsan::dfsan_reaches_function_callback_t callback) { + __dfsan::reaches_function_callback = callback; +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label +dfsan_get_labels_in_signal_reaches_function() { + return __dfsan::labels_in_signal_reaches_function; +} + class Decorator : public __sanitizer::SanitizerCommonDecorator { public: Decorator() : SanitizerCommonDecorator() {} @@ -646,22 +809,16 @@ void PrintInvalidOriginWarning(dfsan_label label, const void *address) { d.Warning(), label, address, d.Default()); } -bool PrintOriginTraceToStr(const void *addr, const char *description, - InternalScopedString *out) { - CHECK(out); - CHECK(dfsan_get_track_origins()); +void PrintInvalidOriginIdWarning(dfsan_origin origin) { Decorator d; + Printf( + " %sOrigin Id %d has invalid origin tracking. This can " + "be a DFSan bug.%s\n", + d.Warning(), origin, d.Default()); +} - const dfsan_label label = *__dfsan::shadow_for(addr); - CHECK(label); - - const dfsan_origin origin = *__dfsan::origin_for(addr); - - out->append(" %sTaint value 0x%x (at %p) origin tracking (%s)%s\n", - d.Origin(), label, addr, description ? description : "", - d.Default()); - - Origin o = Origin::FromRawId(origin); +bool PrintOriginTraceFramesToStr(Origin o, InternalScopedString *out) { + Decorator d; bool found = false; while (o.isChainedOrigin()) { @@ -684,6 +841,25 @@ bool PrintOriginTraceToStr(const void *addr, const char *description, return found; } +bool PrintOriginTraceToStr(const void *addr, const char *description, + InternalScopedString *out) { + CHECK(out); + CHECK(dfsan_get_track_origins()); + Decorator d; + + const dfsan_label label = *__dfsan::shadow_for(addr); + CHECK(label); + + const dfsan_origin origin = *__dfsan::origin_for(addr); + + out->append(" %sTaint value 0x%x (at %p) origin tracking (%s)%s\n", + d.Origin(), label, addr, description ? description : "", + d.Default()); + + Origin o = Origin::FromRawId(origin); + return PrintOriginTraceFramesToStr(o, out); +} + } // namespace extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_print_origin_trace( @@ -709,9 +885,9 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_print_origin_trace( PrintInvalidOriginWarning(label, addr); } -extern "C" SANITIZER_INTERFACE_ATTRIBUTE size_t +extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr dfsan_sprint_origin_trace(const void *addr, const char *description, - char *out_buf, size_t out_buf_size) { + char *out_buf, uptr out_buf_size) { CHECK(out_buf); if (!dfsan_get_track_origins()) { @@ -741,6 +917,50 @@ dfsan_sprint_origin_trace(const void *addr, const char *description, return trace.length(); } +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_print_origin_id_trace( + dfsan_origin origin) { + if (!dfsan_get_track_origins()) { + PrintNoOriginTrackingWarning(); + return; + } + Origin o = Origin::FromRawId(origin); + + InternalScopedString trace; + bool success = PrintOriginTraceFramesToStr(o, &trace); + + if (trace.length()) + Printf("%s", trace.data()); + + if (!success) + PrintInvalidOriginIdWarning(origin); +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr dfsan_sprint_origin_id_trace( + dfsan_origin origin, char *out_buf, uptr out_buf_size) { + CHECK(out_buf); + + if (!dfsan_get_track_origins()) { + PrintNoOriginTrackingWarning(); + return 0; + } + Origin o = Origin::FromRawId(origin); + + InternalScopedString trace; + bool success = PrintOriginTraceFramesToStr(o, &trace); + + if (!success) { + PrintInvalidOriginIdWarning(origin); + return 0; + } + + if (out_buf_size) { + internal_strncpy(out_buf, trace.data(), out_buf_size - 1); + out_buf[out_buf_size - 1] = '\0'; + } + + return trace.length(); +} + extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin dfsan_get_init_origin(const void *addr) { if (!dfsan_get_track_origins()) @@ -780,8 +1000,8 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_print_stack_trace() { stack.Print(); } -extern "C" SANITIZER_INTERFACE_ATTRIBUTE size_t -dfsan_sprint_stack_trace(char *out_buf, size_t out_buf_size) { +extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr +dfsan_sprint_stack_trace(char *out_buf, uptr out_buf_size) { CHECK(out_buf); GET_CALLER_PC_BP; GET_STORE_STACK_TRACE_PC_BP(pc, bp); @@ -837,6 +1057,20 @@ void dfsan_clear_thread_local_state() { } } +SANITIZER_INTERFACE_ATTRIBUTE +void dfsan_set_arg_tls(uptr offset, dfsan_label label) { + // 2x to match ShadowTLSAlignment. + // ShadowTLSAlignment should probably be changed. + // TODO: Consider reducing ShadowTLSAlignment to 1. + // Aligning to 2 bytes is probably a remnant of fast16 mode. + ((dfsan_label *)__dfsan_arg_tls)[offset * 2] = label; +} + +SANITIZER_INTERFACE_ATTRIBUTE +void dfsan_set_arg_origin_tls(uptr offset, dfsan_origin o) { + __dfsan_arg_origin_tls[offset] = o; +} + extern "C" void dfsan_flush() { const uptr maxVirtualAddress = GetMaxUserVirtualAddress(); for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { @@ -857,6 +1091,8 @@ extern "C" void dfsan_flush() { Die(); } } + __dfsan::labels_in_signal_conditional = 0; + __dfsan::labels_in_signal_reaches_function = 0; } // TODO: CheckMemoryLayoutSanity is based on msan. @@ -932,7 +1168,7 @@ static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) { // Consider refactoring these into a shared implementation. bool InitShadow(bool init_origins) { // Let user know mapping parameters first. - VPrintf(1, "dfsan_init %p\n", &__dfsan::dfsan_init); + VPrintf(1, "dfsan_init %p\n", (void *)&__dfsan::dfsan_init); for (unsigned i = 0; i < kMemoryLayoutSize; ++i) VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout[i].name, kMemoryLayout[i].start, kMemoryLayout[i].end - 1); @@ -1005,9 +1241,9 @@ static void DFsanInit(int argc, char **argv, char **envp) { dfsan_allocator_init(); - DFsanThread *main_thread = DFsanThread::Create(nullptr, nullptr, nullptr); + DFsanThread *main_thread = DFsanThread::Create(nullptr, nullptr); SetCurrentThread(main_thread); - main_thread->ThreadStart(); + main_thread->Init(); dfsan_init_is_running = false; dfsan_inited = true; diff --git a/gnu/llvm/compiler-rt/lib/dfsan/dfsan.h b/gnu/llvm/compiler-rt/lib/dfsan/dfsan.h index b212298157e..29938a08de5 100644 --- a/gnu/llvm/compiler-rt/lib/dfsan/dfsan.h +++ b/gnu/llvm/compiler-rt/lib/dfsan/dfsan.h @@ -36,6 +36,12 @@ void dfsan_clear_arg_tls(uptr offset, uptr size); // Zero out the TLS storage. void dfsan_clear_thread_local_state(); +// Set DFSan label and origin TLS of argument for a call. +// Note that offset may not correspond with argument number. +// Some arguments (aggregate/array) will use several offsets. +void dfsan_set_arg_tls(uptr offset, dfsan_label label); +void dfsan_set_arg_origin_tls(uptr offset, dfsan_origin o); + // Return the origin associated with the first taint byte in the size bytes // from the address addr. dfsan_origin dfsan_read_origin_of_first_taint(const void *addr, uptr size); @@ -46,10 +52,14 @@ void dfsan_set_label_origin(dfsan_label label, dfsan_origin origin, void *addr, // Copy or move the origins of the len bytes from src to dst. void dfsan_mem_origin_transfer(const void *dst, const void *src, uptr len); + +// Copy shadow bytes from src to dst. +// Note this preserves distinct taint labels at specific offsets. +void dfsan_mem_shadow_transfer(void *dst, const void *src, uptr len); } // extern "C" template -void dfsan_set_label(dfsan_label label, T &data) { // NOLINT +void dfsan_set_label(dfsan_label label, T &data) { dfsan_set_label(label, (void *)&data, sizeof(T)); } diff --git a/gnu/llvm/compiler-rt/lib/dfsan/dfsan_allocator.cpp b/gnu/llvm/compiler-rt/lib/dfsan/dfsan_allocator.cpp index b2e94564446..5fb8fef213b 100644 --- a/gnu/llvm/compiler-rt/lib/dfsan/dfsan_allocator.cpp +++ b/gnu/llvm/compiler-rt/lib/dfsan/dfsan_allocator.cpp @@ -33,8 +33,12 @@ struct DFsanMapUnmapCallback { void OnUnmap(uptr p, uptr size) const { dfsan_set_label(0, (void *)p, size); } }; -static const uptr kAllocatorSpace = 0x700000000000ULL; -static const uptr kMaxAllowedMallocSize = 8UL << 30; +#if defined(__aarch64__) +const uptr kAllocatorSpace = 0xE00000000000ULL; +#else +const uptr kAllocatorSpace = 0x700000000000ULL; +#endif +const uptr kMaxAllowedMallocSize = 8UL << 30; struct AP64 { // Allocator64 parameters. Deliberately using a short name. static const uptr kSpaceBeg = kAllocatorSpace; @@ -87,6 +91,12 @@ static void *DFsanAllocate(uptr size, uptr alignment, bool zeroise) { BufferedStackTrace stack; ReportAllocationSizeTooBig(size, max_malloc_size, &stack); } + if (UNLIKELY(IsRssLimitExceeded())) { + if (AllocatorMayReturnNull()) + return nullptr; + BufferedStackTrace stack; + ReportRssLimitExceeded(&stack); + } DFsanThread *t = GetCurrentThread(); void *allocated; if (t) { diff --git a/gnu/llvm/compiler-rt/lib/dfsan/dfsan_custom.cpp b/gnu/llvm/compiler-rt/lib/dfsan/dfsan_custom.cpp index 3185184f29c..6f41e225d9e 100644 --- a/gnu/llvm/compiler-rt/lib/dfsan/dfsan_custom.cpp +++ b/gnu/llvm/compiler-rt/lib/dfsan/dfsan_custom.cpp @@ -497,9 +497,7 @@ static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) { } static void *dfsan_memcpy(void *dest, const void *src, size_t n) { - dfsan_label *sdest = shadow_for(dest); - const dfsan_label *ssrc = shadow_for(src); - internal_memcpy((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label)); + dfsan_mem_shadow_transfer(dest, src, n); return internal_memcpy(dest, src, n); } @@ -583,11 +581,8 @@ SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src, dfsan_label src_label, dfsan_label *ret_label) { size_t dest_len = strlen(dest); - char *ret = strcat(dest, src); // NOLINT - dfsan_label *sdest = shadow_for(dest + dest_len); - const dfsan_label *ssrc = shadow_for(src); - internal_memcpy((void *)sdest, (const void *)ssrc, - strlen(src) * sizeof(dfsan_label)); + char *ret = strcat(dest, src); + dfsan_mem_shadow_transfer(dest + dest_len, src, strlen(src)); *ret_label = dest_label; return ret; } @@ -597,13 +592,10 @@ SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat( dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin, dfsan_origin *ret_origin) { size_t dest_len = strlen(dest); - char *ret = strcat(dest, src); // NOLINT - dfsan_label *sdest = shadow_for(dest + dest_len); - const dfsan_label *ssrc = shadow_for(src); + char *ret = strcat(dest, src); size_t src_len = strlen(src); dfsan_mem_origin_transfer(dest + dest_len, src, src_len); - internal_memcpy((void *)sdest, (const void *)ssrc, - src_len * sizeof(dfsan_label)); + dfsan_mem_shadow_transfer(dest + dest_len, src, src_len); *ret_label = dest_label; *ret_origin = dest_origin; return ret; @@ -755,11 +747,12 @@ SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen( static void *DFsanThreadStartFunc(void *arg) { DFsanThread *t = (DFsanThread *)arg; SetCurrentThread(t); + t->Init(); + SetSigProcMask(&t->starting_sigset_, nullptr); return t->ThreadStart(); } static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr, - void *start_routine_trampoline, void *start_routine, void *arg, dfsan_label *ret_label, bool track_origins = false) { @@ -773,8 +766,8 @@ static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr, AdjustStackSize((void *)(const_cast(attr))); DFsanThread *t = - DFsanThread::Create(start_routine_trampoline, - (thread_callback_t)start_routine, arg, track_origins); + DFsanThread::Create((thread_callback_t)start_routine, arg, track_origins); + ScopedBlockSignals block(&t->starting_sigset_); int res = pthread_create(thread, attr, DFsanThreadStartFunc, t); if (attr == &myattr) @@ -784,28 +777,22 @@ static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr, } SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create( - pthread_t *thread, const pthread_attr_t *attr, - void *(*start_routine_trampoline)(void *, void *, dfsan_label, - dfsan_label *), - void *start_routine, void *arg, dfsan_label thread_label, - dfsan_label attr_label, dfsan_label start_routine_label, - dfsan_label arg_label, dfsan_label *ret_label) { - return dfsan_pthread_create(thread, attr, (void *)start_routine_trampoline, - start_routine, arg, ret_label); + pthread_t *thread, const pthread_attr_t *attr, void *start_routine, + void *arg, dfsan_label thread_label, dfsan_label attr_label, + dfsan_label start_routine_label, dfsan_label arg_label, + dfsan_label *ret_label) { + return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label); } SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create( - pthread_t *thread, const pthread_attr_t *attr, - void *(*start_routine_trampoline)(void *, void *, dfsan_label, - dfsan_label *, dfsan_origin, - dfsan_origin *), - void *start_routine, void *arg, dfsan_label thread_label, - dfsan_label attr_label, dfsan_label start_routine_label, - dfsan_label arg_label, dfsan_label *ret_label, dfsan_origin thread_origin, + pthread_t *thread, const pthread_attr_t *attr, void *start_routine, + void *arg, dfsan_label thread_label, dfsan_label attr_label, + dfsan_label start_routine_label, dfsan_label arg_label, + dfsan_label *ret_label, dfsan_origin thread_origin, dfsan_origin attr_origin, dfsan_origin start_routine_origin, dfsan_origin arg_origin, dfsan_origin *ret_origin) { - return dfsan_pthread_create(thread, attr, (void *)start_routine_trampoline, - start_routine, arg, ret_label, true); + return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label, + true); } SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread, @@ -830,22 +817,7 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join( } struct dl_iterate_phdr_info { - int (*callback_trampoline)(void *callback, struct dl_phdr_info *info, - size_t size, void *data, dfsan_label info_label, - dfsan_label size_label, dfsan_label data_label, - dfsan_label *ret_label); - void *callback; - void *data; -}; - -struct dl_iterate_phdr_origin_info { - int (*callback_trampoline)(void *callback, struct dl_phdr_info *info, - size_t size, void *data, dfsan_label info_label, - dfsan_label size_label, dfsan_label data_label, - dfsan_label *ret_label, dfsan_origin info_origin, - dfsan_origin size_origin, dfsan_origin data_origin, - dfsan_origin *ret_origin); - void *callback; + int (*callback)(struct dl_phdr_info *info, size_t size, void *data); void *data; }; @@ -857,53 +829,28 @@ int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) { dfsan_set_label( 0, const_cast(reinterpret_cast(info->dlpi_phdr)), sizeof(*info->dlpi_phdr) * info->dlpi_phnum); - dfsan_label ret_label; - return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0, - 0, &ret_label); -} -int dl_iterate_phdr_origin_cb(struct dl_phdr_info *info, size_t size, - void *data) { - dl_iterate_phdr_origin_info *dipi = (dl_iterate_phdr_origin_info *)data; - dfsan_set_label(0, *info); - dfsan_set_label(0, const_cast(info->dlpi_name), - strlen(info->dlpi_name) + 1); - dfsan_set_label( - 0, const_cast(reinterpret_cast(info->dlpi_phdr)), - sizeof(*info->dlpi_phdr) * info->dlpi_phnum); - dfsan_label ret_label; - dfsan_origin ret_origin; - return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0, - 0, &ret_label, 0, 0, 0, &ret_origin); + dfsan_clear_thread_local_state(); + return dipi->callback(info, size, dipi->data); } SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr( - int (*callback_trampoline)(void *callback, struct dl_phdr_info *info, - size_t size, void *data, dfsan_label info_label, - dfsan_label size_label, dfsan_label data_label, - dfsan_label *ret_label), - void *callback, void *data, dfsan_label callback_label, - dfsan_label data_label, dfsan_label *ret_label) { - dl_iterate_phdr_info dipi = { callback_trampoline, callback, data }; + int (*callback)(struct dl_phdr_info *info, size_t size, void *data), + void *data, dfsan_label callback_label, dfsan_label data_label, + dfsan_label *ret_label) { + dl_iterate_phdr_info dipi = {callback, data}; *ret_label = 0; return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi); } SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr( - int (*callback_trampoline)(void *callback, struct dl_phdr_info *info, - size_t size, void *data, dfsan_label info_label, - dfsan_label size_label, dfsan_label data_label, - dfsan_label *ret_label, dfsan_origin info_origin, - dfsan_origin size_origin, - dfsan_origin data_origin, - dfsan_origin *ret_origin), - void *callback, void *data, dfsan_label callback_label, - dfsan_label data_label, dfsan_label *ret_label, - dfsan_origin callback_origin, dfsan_origin data_origin, - dfsan_origin *ret_origin) { - dl_iterate_phdr_origin_info dipi = {callback_trampoline, callback, data}; + int (*callback)(struct dl_phdr_info *info, size_t size, void *data), + void *data, dfsan_label callback_label, dfsan_label data_label, + dfsan_label *ret_label, dfsan_origin callback_origin, + dfsan_origin data_origin, dfsan_origin *ret_origin) { + dl_iterate_phdr_info dipi = {callback, data}; *ret_label = 0; - return dl_iterate_phdr(dl_iterate_phdr_origin_cb, &dipi); + return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi); } // This function is only available for glibc 2.27 or newer. Mark it weak so @@ -1026,6 +973,33 @@ char *__dfso_get_current_dir_name(dfsan_label *ret_label, return __dfsw_get_current_dir_name(ret_label); } +// This function is only available for glibc 2.25 or newer. Mark it weak so +// linking succeeds with older glibcs. +SANITIZER_WEAK_ATTRIBUTE int getentropy(void *buffer, size_t length); + +SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getentropy(void *buffer, size_t length, + dfsan_label buffer_label, + dfsan_label length_label, + dfsan_label *ret_label) { + int ret = getentropy(buffer, length); + if (ret == 0) { + dfsan_set_label(0, buffer, length); + } + *ret_label = 0; + return ret; +} + +SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getentropy(void *buffer, size_t length, + dfsan_label buffer_label, + dfsan_label length_label, + dfsan_label *ret_label, + dfsan_origin buffer_origin, + dfsan_origin length_origin, + dfsan_origin *ret_origin) { + return __dfsw_getentropy(buffer, length, buffer_label, length_label, + ret_label); +} + SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label, dfsan_label len_label, dfsan_label *ret_label) { @@ -1088,10 +1062,9 @@ int __dfso_getrusage(int who, struct rusage *usage, dfsan_label who_label, SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label, dfsan_label src_label, dfsan_label *ret_label) { - char *ret = strcpy(dest, src); // NOLINT + char *ret = strcpy(dest, src); if (ret) { - internal_memcpy(shadow_for(dest), shadow_for(src), - sizeof(dfsan_label) * (strlen(src) + 1)); + dfsan_mem_shadow_transfer(dest, src, strlen(src) + 1); } *ret_label = dst_label; return ret; @@ -1102,12 +1075,11 @@ char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label, dfsan_label src_label, dfsan_label *ret_label, dfsan_origin dst_origin, dfsan_origin src_origin, dfsan_origin *ret_origin) { - char *ret = strcpy(dest, src); // NOLINT + char *ret = strcpy(dest, src); if (ret) { size_t str_len = strlen(src) + 1; dfsan_mem_origin_transfer(dest, src, str_len); - internal_memcpy(shadow_for(dest), shadow_for(src), - sizeof(dfsan_label) * str_len); + dfsan_mem_shadow_transfer(dest, src, str_len); } *ret_label = dst_label; *ret_origin = dst_origin; @@ -1609,10 +1581,7 @@ static void SignalHandler(int signo) { SignalHandlerScope signal_handler_scope; ScopedClearThreadLocalState scoped_clear_tls; - // Clear shadows for all inputs provided by system. This is why DFSan - // instrumentation generates a trampoline function to each function pointer, - // and uses the trampoline to clear shadows. However sigaction does not use - // a function pointer directly, so we have to do this manually. + // Clear shadows for all inputs provided by system. dfsan_clear_arg_tls(0, sizeof(dfsan_label)); typedef void (*signal_cb)(int x); @@ -1713,22 +1682,18 @@ static sighandler_t dfsan_signal(int signum, sighandler_t handler, } SANITIZER_INTERFACE_ATTRIBUTE -sighandler_t __dfsw_signal(int signum, - void *(*handler_trampoline)(void *, int, dfsan_label, - dfsan_label *), - sighandler_t handler, dfsan_label signum_label, - dfsan_label handler_label, dfsan_label *ret_label) { +sighandler_t __dfsw_signal(int signum, sighandler_t handler, + dfsan_label signum_label, dfsan_label handler_label, + dfsan_label *ret_label) { return dfsan_signal(signum, handler, ret_label); } SANITIZER_INTERFACE_ATTRIBUTE -sighandler_t __dfso_signal( - int signum, - void *(*handler_trampoline)(void *, int, dfsan_label, dfsan_label *, - dfsan_origin, dfsan_origin *), - sighandler_t handler, dfsan_label signum_label, dfsan_label handler_label, - dfsan_label *ret_label, dfsan_origin signum_origin, - dfsan_origin handler_origin, dfsan_origin *ret_origin) { +sighandler_t __dfso_signal(int signum, sighandler_t handler, + dfsan_label signum_label, dfsan_label handler_label, + dfsan_label *ret_label, dfsan_origin signum_origin, + dfsan_origin handler_origin, + dfsan_origin *ret_origin) { return dfsan_signal(signum, handler, ret_label); } @@ -2068,47 +2033,62 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername( addrlen_label, ret_label); } -// Type of the trampoline function passed to the custom version of -// dfsan_set_write_callback. -typedef void (*write_trampoline_t)( - void *callback, - int fd, const void *buf, ssize_t count, - dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label); - -typedef void (*write_origin_trampoline_t)( - void *callback, int fd, const void *buf, ssize_t count, - dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label, - dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin); +// Type of the function passed to dfsan_set_write_callback. +typedef void (*write_dfsan_callback_t)(int fd, const void *buf, ssize_t count); // Calls to dfsan_set_write_callback() set the values in this struct. // Calls to the custom version of write() read (and invoke) them. static struct { - write_trampoline_t write_callback_trampoline = nullptr; - void *write_callback = nullptr; + write_dfsan_callback_t write_callback = nullptr; } write_callback_info; -static struct { - write_origin_trampoline_t write_callback_trampoline = nullptr; - void *write_callback = nullptr; -} write_origin_callback_info; - -SANITIZER_INTERFACE_ATTRIBUTE void -__dfsw_dfsan_set_write_callback( - write_trampoline_t write_callback_trampoline, - void *write_callback, - dfsan_label write_callback_label, +SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_dfsan_set_write_callback( + write_dfsan_callback_t write_callback, dfsan_label write_callback_label, dfsan_label *ret_label) { - write_callback_info.write_callback_trampoline = write_callback_trampoline; write_callback_info.write_callback = write_callback; } SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback( - write_origin_trampoline_t write_callback_trampoline, void *write_callback, - dfsan_label write_callback_label, dfsan_label *ret_label, - dfsan_origin write_callback_origin, dfsan_origin *ret_origin) { - write_origin_callback_info.write_callback_trampoline = - write_callback_trampoline; - write_origin_callback_info.write_callback = write_callback; + write_dfsan_callback_t write_callback, dfsan_label write_callback_label, + dfsan_label *ret_label, dfsan_origin write_callback_origin, + dfsan_origin *ret_origin) { + write_callback_info.write_callback = write_callback; +} + +static inline void setup_tls_args_for_write_callback( + dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label, + bool origins, dfsan_origin fd_origin, dfsan_origin buf_origin, + dfsan_origin count_origin) { + // The callback code will expect argument shadow labels in the args TLS, + // and origin labels in the origin args TLS. + // Previously this was done by a trampoline, but we want to remove this: + // https://github.com/llvm/llvm-project/issues/54172 + // + // Instead, this code is manually setting up the args TLS data. + // + // The offsets used need to correspond with the instrumentation code, + // see llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp + // DFSanFunction::getShadowForTLSArgument. + // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L1684 + // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L125 + // + // Here the arguments are all primitives, but it can be more complex + // to compute offsets for array/aggregate type arguments. + // + // TODO(browneee): Consider a builtin to improve maintainabliity. + // With a builtin, we would provide the argument labels via builtin, + // and the builtin would reuse parts of the instrumentation code to ensure + // that this code and the instrumentation can never be out of sync. + // Note: Currently DFSan instrumentation does not run on this code, so + // the builtin may need to be handled outside DFSan instrumentation. + dfsan_set_arg_tls(0, fd_label); + dfsan_set_arg_tls(1, buf_label); + dfsan_set_arg_tls(2, count_label); + if (origins) { + dfsan_set_arg_origin_tls(0, fd_origin); + dfsan_set_arg_origin_tls(1, buf_origin); + dfsan_set_arg_origin_tls(2, count_origin); + } } SANITIZER_INTERFACE_ATTRIBUTE int @@ -2116,10 +2096,9 @@ __dfsw_write(int fd, const void *buf, size_t count, dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label) { if (write_callback_info.write_callback) { - write_callback_info.write_callback_trampoline( - write_callback_info.write_callback, - fd, buf, count, - fd_label, buf_label, count_label); + setup_tls_args_for_write_callback(fd_label, buf_label, count_label, false, + 0, 0, 0); + write_callback_info.write_callback(fd, buf, count); } *ret_label = 0; @@ -2131,10 +2110,10 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write( dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin, dfsan_origin *ret_origin) { - if (write_origin_callback_info.write_callback) { - write_origin_callback_info.write_callback_trampoline( - write_origin_callback_info.write_callback, fd, buf, count, fd_label, - buf_label, count_label, fd_origin, buf_origin, count_origin); + if (write_callback_info.write_callback) { + setup_tls_args_for_write_callback(fd_label, buf_label, count_label, true, + fd_origin, buf_origin, count_origin); + write_callback_info.write_callback(fd, buf, count); } *ret_label = 0; @@ -2339,9 +2318,8 @@ static int format_buffer(char *str, size_t size, const char *fmt, formatter.num_written_bytes(retval)); } va_labels++; - internal_memcpy(shadow_for(formatter.str_cur()), shadow_for(arg), - sizeof(dfsan_label) * - formatter.num_written_bytes(retval)); + dfsan_mem_shadow_transfer(formatter.str_cur(), arg, + formatter.num_written_bytes(retval)); end_fmt = true; break; } @@ -2489,7 +2467,8 @@ pid_t __dfso_fork(dfsan_label *ret_label, dfsan_origin *ret_origin) { SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *, u32 *) {} -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, void) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr *beg, + const uptr *end) {} SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {} SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {} diff --git a/gnu/llvm/compiler-rt/lib/dfsan/dfsan_interceptors.cpp b/gnu/llvm/compiler-rt/lib/dfsan/dfsan_interceptors.cpp index 92be4fc87d4..d8fb9ea8661 100644 --- a/gnu/llvm/compiler-rt/lib/dfsan/dfsan_interceptors.cpp +++ b/gnu/llvm/compiler-rt/lib/dfsan/dfsan_interceptors.cpp @@ -17,6 +17,7 @@ #include "dfsan/dfsan.h" #include "dfsan/dfsan_thread.h" #include "interception/interception.h" +#include "sanitizer_common/sanitizer_allocator_dlsym.h" #include "sanitizer_common/sanitizer_allocator_interface.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_errno.h" @@ -26,11 +27,11 @@ using namespace __sanitizer; -namespace { +static bool interceptors_initialized; -bool interceptors_initialized; - -} // namespace +struct DlsymAlloc : public DlSymAllocator { + static bool UseImpl() { return !__dfsan::dfsan_inited; } +}; INTERCEPTOR(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size) { return __dfsan::dfsan_reallocarray(ptr, nmemb, size); @@ -47,63 +48,37 @@ INTERCEPTOR(void *, aligned_alloc, SIZE_T alignment, SIZE_T size) { return __dfsan::dfsan_aligned_alloc(alignment, size); } -static uptr allocated_for_dlsym; -static const uptr kDlsymAllocPoolSize = 1024; -static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize]; - -static bool IsInDlsymAllocPool(const void *ptr) { - uptr off = (uptr)ptr - (uptr)alloc_memory_for_dlsym; - return off < sizeof(alloc_memory_for_dlsym); -} - -static void *AllocateFromLocalPool(uptr size_in_bytes) { - uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize; - void *mem = (void *)&alloc_memory_for_dlsym[allocated_for_dlsym]; - allocated_for_dlsym += size_in_words; - CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize); - return mem; -} - INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) { - if (UNLIKELY(!__dfsan::dfsan_inited)) - // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. - return AllocateFromLocalPool(nmemb * size); + if (DlsymAlloc::Use()) + return DlsymAlloc::Callocate(nmemb, size); return __dfsan::dfsan_calloc(nmemb, size); } INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) { - if (UNLIKELY(IsInDlsymAllocPool(ptr))) { - uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym; - uptr copy_size = Min(size, kDlsymAllocPoolSize - offset); - void *new_ptr; - if (UNLIKELY(!__dfsan::dfsan_inited)) { - new_ptr = AllocateFromLocalPool(copy_size); - } else { - copy_size = size; - new_ptr = __dfsan::dfsan_malloc(copy_size); - } - internal_memcpy(new_ptr, ptr, copy_size); - return new_ptr; - } + if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) + return DlsymAlloc::Realloc(ptr, size); return __dfsan::dfsan_realloc(ptr, size); } INTERCEPTOR(void *, malloc, SIZE_T size) { - if (UNLIKELY(!__dfsan::dfsan_inited)) - // Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym. - return AllocateFromLocalPool(size); + if (DlsymAlloc::Use()) + return DlsymAlloc::Allocate(size); return __dfsan::dfsan_malloc(size); } INTERCEPTOR(void, free, void *ptr) { - if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr))) + if (!ptr) return; + if (DlsymAlloc::PointerIsMine(ptr)) + return DlsymAlloc::Free(ptr); return __dfsan::dfsan_deallocate(ptr); } INTERCEPTOR(void, cfree, void *ptr) { - if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr))) + if (!ptr) return; + if (DlsymAlloc::PointerIsMine(ptr)) + return DlsymAlloc::Free(ptr); return __dfsan::dfsan_deallocate(ptr); } @@ -152,12 +127,12 @@ INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { if (__dfsan::dfsan_init_is_running) \ return REAL(func)(__VA_ARGS__); \ ENSURE_DFSAN_INITED(); \ - dfsan_set_label(0, __errno_location(), sizeof(int)); /* NOLINT */ + dfsan_set_label(0, __errno_location(), sizeof(int)); INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags, int fd, OFF_T offset) { if (common_flags()->detect_write_exec) - ReportMmapWriteExec(prot); + ReportMmapWriteExec(prot, flags); if (!__dfsan::dfsan_inited) return (void *)internal_mmap(addr, length, prot, flags, fd, offset); COMMON_INTERCEPTOR_ENTER(mmap, addr, length, prot, flags, fd, offset); @@ -171,7 +146,7 @@ INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags, INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags, int fd, OFF64_T offset) { if (common_flags()->detect_write_exec) - ReportMmapWriteExec(prot); + ReportMmapWriteExec(prot, flags); if (!__dfsan::dfsan_inited) return (void *)internal_mmap(addr, length, prot, flags, fd, offset); COMMON_INTERCEPTOR_ENTER(mmap64, addr, length, prot, flags, fd, offset); diff --git a/gnu/llvm/compiler-rt/lib/dfsan/dfsan_platform.h b/gnu/llvm/compiler-rt/lib/dfsan/dfsan_platform.h index 9b4333ee99d..b849b4b528a 100644 --- a/gnu/llvm/compiler-rt/lib/dfsan/dfsan_platform.h +++ b/gnu/llvm/compiler-rt/lib/dfsan/dfsan_platform.h @@ -33,6 +33,32 @@ struct MappingDesc { #if SANITIZER_LINUX && SANITIZER_WORDSIZE == 64 +# if defined(__aarch64__) +// The mapping assumes 48-bit VMA. AArch64 maps: +// - 0x0000000000000-0x0100000000000: 39/42/48-bits program own segments +// - 0x0a00000000000-0x0b00000000000: 48-bits PIE program segments +// Ideally, this would extend to 0x0c00000000000 (2^45 bytes - the +// maximum ASLR region for 48-bit VMA) but it is too hard to fit in +// the larger app/shadow/origin regions. +// - 0x0e00000000000-0x1000000000000: 48-bits libraries segments +const MappingDesc kMemoryLayout[] = { + {0X0000000000000, 0X0100000000000, MappingDesc::APP, "app-10-13"}, + {0X0100000000000, 0X0200000000000, MappingDesc::SHADOW, "shadow-14"}, + {0X0200000000000, 0X0300000000000, MappingDesc::INVALID, "invalid"}, + {0X0300000000000, 0X0400000000000, MappingDesc::ORIGIN, "origin-14"}, + {0X0400000000000, 0X0600000000000, MappingDesc::SHADOW, "shadow-15"}, + {0X0600000000000, 0X0800000000000, MappingDesc::ORIGIN, "origin-15"}, + {0X0800000000000, 0X0A00000000000, MappingDesc::INVALID, "invalid"}, + {0X0A00000000000, 0X0B00000000000, MappingDesc::APP, "app-14"}, + {0X0B00000000000, 0X0C00000000000, MappingDesc::SHADOW, "shadow-10-13"}, + {0X0C00000000000, 0X0D00000000000, MappingDesc::INVALID, "invalid"}, + {0X0D00000000000, 0X0E00000000000, MappingDesc::ORIGIN, "origin-10-13"}, + {0X0E00000000000, 0X1000000000000, MappingDesc::APP, "app-15"}, +}; +# define MEM_TO_SHADOW(mem) ((uptr)mem ^ 0xB00000000000ULL) +# define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x200000000000ULL) + +# else // All of the following configurations are supported. // ASLR disabled: main executable and DSOs at 0x555550000000 // PIE and ASLR: main executable and DSOs at 0x7f0000000000 @@ -51,8 +77,9 @@ const MappingDesc kMemoryLayout[] = { {0x600000000000ULL, 0x610000000000ULL, MappingDesc::ORIGIN, "origin-1"}, {0x610000000000ULL, 0x700000000000ULL, MappingDesc::INVALID, "invalid"}, {0x700000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}}; -# define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL) -# define SHADOW_TO_ORIGIN(mem) (((uptr)(mem)) + 0x100000000000ULL) +# define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL) +# define SHADOW_TO_ORIGIN(mem) (((uptr)(mem)) + 0x100000000000ULL) +# endif #else # error "Unsupported platform" diff --git a/gnu/llvm/compiler-rt/lib/dfsan/dfsan_thread.cpp b/gnu/llvm/compiler-rt/lib/dfsan/dfsan_thread.cpp index 6869cf23158..e64f0f818fb 100644 --- a/gnu/llvm/compiler-rt/lib/dfsan/dfsan_thread.cpp +++ b/gnu/llvm/compiler-rt/lib/dfsan/dfsan_thread.cpp @@ -7,13 +7,11 @@ namespace __dfsan { -DFsanThread *DFsanThread::Create(void *start_routine_trampoline, - thread_callback_t start_routine, void *arg, +DFsanThread *DFsanThread::Create(thread_callback_t start_routine, void *arg, bool track_origins) { uptr PageSize = GetPageSizeCached(); uptr size = RoundUpTo(sizeof(DFsanThread), PageSize); DFsanThread *thread = (DFsanThread *)MmapOrDie(size, __func__); - thread->start_routine_trampoline_ = start_routine_trampoline; thread->start_routine_ = start_routine; thread->arg_ = arg; thread->track_origins_ = track_origins; @@ -67,8 +65,6 @@ void DFsanThread::Destroy() { } thread_return_t DFsanThread::ThreadStart() { - Init(); - if (!start_routine_) { // start_routine_ == 0 if we're on the main thread or on one of the // OS X libdispatch worker threads. But nobody is supposed to call @@ -76,23 +72,15 @@ thread_return_t DFsanThread::ThreadStart() { return 0; } - CHECK(start_routine_trampoline_); - - typedef void *(*thread_callback_trampoline_t)(void *, void *, dfsan_label, - dfsan_label *); - typedef void *(*thread_callback_origin_trampoline_t)( - void *, void *, dfsan_label, dfsan_label *, dfsan_origin, dfsan_origin *); - - dfsan_label ret_label; - if (!track_origins_) - return ((thread_callback_trampoline_t) - start_routine_trampoline_)((void *)start_routine_, arg_, 0, - &ret_label); + // The only argument is void* arg. + // + // We have never supported propagating the pointer arg as tainted, + // __dfsw_pthread_create/__dfso_pthread_create ignore the taint label. + // Note that the bytes pointed-to (probably the much more common case) + // can still have taint labels attached to them. + dfsan_clear_thread_local_state(); - dfsan_origin ret_origin; - return ((thread_callback_origin_trampoline_t) - start_routine_trampoline_)((void *)start_routine_, arg_, 0, - &ret_label, 0, &ret_origin); + return start_routine_(arg_); } DFsanThread::StackBounds DFsanThread::GetStackBounds() const { diff --git a/gnu/llvm/compiler-rt/lib/dfsan/dfsan_thread.h b/gnu/llvm/compiler-rt/lib/dfsan/dfsan_thread.h index 8dde626f556..ebc25499e26 100644 --- a/gnu/llvm/compiler-rt/lib/dfsan/dfsan_thread.h +++ b/gnu/llvm/compiler-rt/lib/dfsan/dfsan_thread.h @@ -1,5 +1,4 @@ -//===-- dfsan_thread.h -------------------------------------------*- C++ -//-*-===// +//===-- dfsan_thread.h ------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -16,6 +15,7 @@ #include "dfsan_allocator.h" #include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_posix.h" namespace __dfsan { @@ -24,8 +24,7 @@ class DFsanThread { // NOTE: There is no DFsanThread constructor. It is allocated // via mmap() and *must* be valid in zero-initialized state. - static DFsanThread *Create(void *start_routine_trampoline, - thread_callback_t start_routine, void *arg, + static DFsanThread *Create(thread_callback_t start_routine, void *arg, bool track_origins = false); static void TSDDtor(void *tsd); void Destroy(); @@ -46,6 +45,7 @@ class DFsanThread { DFsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; } int destructor_iterations_; + __sanitizer_sigset_t starting_sigset_; private: void SetThreadStackAndTls(); @@ -58,7 +58,6 @@ class DFsanThread { bool AddrIsInStack(uptr addr); - void *start_routine_trampoline_; thread_callback_t start_routine_; void *arg_; bool track_origins_; diff --git a/gnu/llvm/compiler-rt/lib/dfsan/done_abilist.txt b/gnu/llvm/compiler-rt/lib/dfsan/done_abilist.txt index 3c2670e04c2..ff8a37fbf42 100644 --- a/gnu/llvm/compiler-rt/lib/dfsan/done_abilist.txt +++ b/gnu/llvm/compiler-rt/lib/dfsan/done_abilist.txt @@ -30,16 +30,32 @@ fun:dfsan_flush=uninstrumented fun:dfsan_flush=discard fun:dfsan_print_origin_trace=uninstrumented fun:dfsan_print_origin_trace=discard +fun:dfsan_print_origin_id_trace=uninstrumented +fun:dfsan_print_origin_id_trace=discard fun:dfsan_sprint_origin_trace=uninstrumented fun:dfsan_sprint_origin_trace=discard +fun:dfsan_sprint_origin_id_trace=uninstrumented +fun:dfsan_sprint_origin_id_trace=discard fun:dfsan_sprint_stack_trace=uninstrumented fun:dfsan_sprint_stack_trace=discard fun:dfsan_get_origin=uninstrumented fun:dfsan_get_origin=custom +fun:dfsan_read_origin_of_first_taint=uninstrumented +fun:dfsan_read_origin_of_first_taint=discard fun:dfsan_get_init_origin=uninstrumented fun:dfsan_get_init_origin=discard fun:dfsan_get_track_origins=uninstrumented fun:dfsan_get_track_origins=discard +fun:dfsan_set_conditional_callback=uninstrumented +fun:dfsan_set_conditional_callback=discard +fun:dfsan_get_labels_in_signal_conditional=uninstrumented +fun:dfsan_get_labels_in_signal_conditional=discard +fun:dfsan_set_reaches_function_callback=uninstrumented +fun:dfsan_set_reaches_function_callback=discard +fun:dfsan_get_labels_in_signal_reaches_function=uninstrumented +fun:dfsan_get_labels_in_signal_reaches_function=discard +fun:dfsan_reaches_function_callback=uninstrumented +fun:dfsan_reaches_function_callback=discard ############################################################################### # glibc @@ -218,6 +234,7 @@ fun:fgets=custom fun:fstat=custom fun:getcwd=custom fun:get_current_dir_name=custom +fun:getentropy=custom fun:gethostname=custom fun:getpeername=custom fun:getrlimit=custom @@ -268,7 +285,7 @@ fun:strrchr=custom fun:strstr=custom # Functions which take action based on global state, such as running a callback -# set by a sepperate function. +# set by a separate function. fun:write=custom # Functions that take a callback (wrap the callback manually). diff --git a/gnu/llvm/compiler-rt/lib/dfsan/libc_ubuntu1404_abilist.txt b/gnu/llvm/compiler-rt/lib/dfsan/libc_ubuntu1404_abilist.txt index a1ea0a06b53..433092e2b27 100644 --- a/gnu/llvm/compiler-rt/lib/dfsan/libc_ubuntu1404_abilist.txt +++ b/gnu/llvm/compiler-rt/lib/dfsan/libc_ubuntu1404_abilist.txt @@ -1852,6 +1852,7 @@ fun:getdirentries64=uninstrumented fun:getdomainname=uninstrumented fun:getdtablesize=uninstrumented fun:getegid=uninstrumented +fun:getentropy=uninstrumented fun:getenv=uninstrumented fun:geteuid=uninstrumented fun:getfsent=uninstrumented diff --git a/gnu/llvm/compiler-rt/lib/dfsan/scripts/build-libc-list.py b/gnu/llvm/compiler-rt/lib/dfsan/scripts/build-libc-list.py index 40805c01916..524749640e4 100755 --- a/gnu/llvm/compiler-rt/lib/dfsan/scripts/build-libc-list.py +++ b/gnu/llvm/compiler-rt/lib/dfsan/scripts/build-libc-list.py @@ -11,6 +11,30 @@ # uninstrumented, thus allowing the instrumentation pass to treat calls to those # functions correctly. +# Typical usage will list runtime libraries which are not instrumented by dfsan. +# This would include libc, and compiler builtins. +# +# ./build-libc-list.py \ +# --lib-file=/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 \ +# --lib-file=/lib/x86_64-linux-gnu/libanl.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libBrokenLocale.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libcidn.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libcrypt.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libc.so.6 \ +# --lib-file=/lib/x86_64-linux-gnu/libdl.so.2 \ +# --lib-file=/lib/x86_64-linux-gnu/libm.so.6 \ +# --lib-file=/lib/x86_64-linux-gnu/libnsl.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libpthread.so.0 \ +# --lib-file=/lib/x86_64-linux-gnu/libresolv.so.2 \ +# --lib-file=/lib/x86_64-linux-gnu/librt.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libthread_db.so.1 \ +# --lib-file=/lib/x86_64-linux-gnu/libutil.so.1 \ +# --lib-file=/usr/lib/x86_64-linux-gnu/libc_nonshared.a \ +# --lib-file=/usr/lib/x86_64-linux-gnu/libpthread_nonshared.a \ +# --lib-file=/lib/x86_64-linux-gnu/libgcc_s.so.1 \ +# --lib-file=/usr/lib/gcc/x86_64-linux-gnu/4.6/libgcc.a \ +# --error-missing-lib + import os import subprocess import sys @@ -33,61 +57,34 @@ def defined_function_list(object): p = OptionParser() -p.add_option('--libc-dso-path', metavar='PATH', - help='path to libc DSO directory', - default='/lib/x86_64-linux-gnu') -p.add_option('--libc-archive-path', metavar='PATH', - help='path to libc archive directory', - default='/usr/lib/x86_64-linux-gnu') - -p.add_option('--libgcc-dso-path', metavar='PATH', - help='path to libgcc DSO directory', - default='/lib/x86_64-linux-gnu') -p.add_option('--libgcc-archive-path', metavar='PATH', - help='path to libgcc archive directory', - default='/usr/lib/gcc/x86_64-linux-gnu/4.6') +p.add_option('--lib-file', action='append', metavar='PATH', + help='Specific library files to add.', + default=[]) -p.add_option('--with-libstdcxx', action='store_true', - dest='with_libstdcxx', - help='include libstdc++ in the list (inadvisable)') -p.add_option('--libstdcxx-dso-path', metavar='PATH', - help='path to libstdc++ DSO directory', - default='/usr/lib/x86_64-linux-gnu') +p.add_option('--error-missing-lib', action='store_true', + help='Make this script exit with an error code if any library is missing.', + dest='error_missing_lib', default=False) (options, args) = p.parse_args() -libs = [os.path.join(options.libc_dso_path, name) for name in - ['ld-linux-x86-64.so.2', - 'libanl.so.1', - 'libBrokenLocale.so.1', - 'libcidn.so.1', - 'libcrypt.so.1', - 'libc.so.6', - 'libdl.so.2', - 'libm.so.6', - 'libnsl.so.1', - 'libpthread.so.0', - 'libresolv.so.2', - 'librt.so.1', - 'libthread_db.so.1', - 'libutil.so.1']] -libs += [os.path.join(options.libc_archive_path, name) for name in - ['libc_nonshared.a', - 'libpthread_nonshared.a']] - -libs.append(os.path.join(options.libgcc_dso_path, 'libgcc_s.so.1')) -libs.append(os.path.join(options.libgcc_archive_path, 'libgcc.a')) - -if options.with_libstdcxx: - libs.append(os.path.join(options.libstdcxx_dso_path, 'libstdc++.so.6')) +libs = options.lib_file +if not libs: + print >> sys.stderr, 'No libraries provided.' + exit(1) +missing_lib = False functions = [] for l in libs: if os.path.exists(l): functions += defined_function_list(l) else: + missing_lib = True print >> sys.stderr, 'warning: library %s not found' % l +if options.error_missing_lib and missing_lib: + print >> sys.stderr, 'Exiting with failure code due to missing library.' + exit(1) + functions = list(set(functions)) functions.sort() diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/CMakeLists.txt b/gnu/llvm/compiler-rt/lib/fuzzer/CMakeLists.txt index 3201ed279a6..a9a10f724d1 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/lib/fuzzer/CMakeLists.txt @@ -6,6 +6,8 @@ set(LIBFUZZER_SOURCES FuzzerExtFunctionsWeak.cpp FuzzerExtFunctionsWindows.cpp FuzzerExtraCounters.cpp + FuzzerExtraCountersDarwin.cpp + FuzzerExtraCountersWindows.cpp FuzzerFork.cpp FuzzerIO.cpp FuzzerIOPosix.cpp @@ -64,18 +66,19 @@ if(OS_NAME MATCHES "Linux|Fuchsia" AND append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ LIBFUZZER_CFLAGS) elseif(TARGET cxx-headers OR HAVE_LIBCXX) # libFuzzer uses C++ standard library headers. + list(APPEND LIBFUZZER_CFLAGS ${COMPILER_RT_CXX_CFLAGS}) set(LIBFUZZER_DEPS cxx-headers) endif() append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG -fno-omit-frame-pointer LIBFUZZER_CFLAGS) if (CMAKE_CXX_FLAGS MATCHES "fsanitize-coverage") - list(APPEND LIBFUZZER_CFLAGS -fno-sanitize-coverage=trace-pc-guard,edge,trace-cmp,indirect-calls,8bit-counters) + list(APPEND LIBFUZZER_CFLAGS -fsanitize-coverage=0) endif() if(MSVC) # Silence warnings by turning off exceptions in MSVC headers and avoid an - # error by unecessarily defining thread_local when it isn't even used on + # error by unnecessarily defining thread_local when it isn't even used on # Windows. list(APPEND LIBFUZZER_CFLAGS -D_HAS_EXCEPTIONS=0) else() @@ -136,15 +139,15 @@ if(OS_NAME MATCHES "Linux|Fuchsia" AND COMPILER_RT_LIBCXX_PATH AND COMPILER_RT_LIBCXXABI_PATH) macro(partially_link_libcxx name dir arch) - if(${arch} MATCHES "i386") - set(EMULATION_ARGUMENT "-m" "elf_i386") - else() - set(EMULATION_ARGUMENT "") + get_target_flags_for_arch(${arch} target_cflags) + if(CMAKE_CXX_COMPILER_ID MATCHES Clang) + get_compiler_rt_target(${arch} target) + set(target_cflags --target=${target} ${target_cflags}) endif() set(cxx_${arch}_merge_dir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${arch}_merge.dir") file(MAKE_DIRECTORY ${cxx_${arch}_merge_dir}) add_custom_command(TARGET clang_rt.${name}-${arch} POST_BUILD - COMMAND ${CMAKE_LINKER} ${EMULATION_ARGUMENT} --whole-archive "$" --no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o + COMMAND ${CMAKE_CXX_COMPILER} ${target_cflags} -Wl,--whole-archive "$" -Wl,--no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o COMMAND ${CMAKE_OBJCOPY} --localize-hidden ${name}.o COMMAND ${CMAKE_COMMAND} -E remove "$" COMMAND ${CMAKE_AR} qcs "$" ${name}.o @@ -160,7 +163,8 @@ if(OS_NAME MATCHES "Linux|Fuchsia" AND CMAKE_ARGS -DCMAKE_CXX_COMPILER_WORKS=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DLIBCXXABI_ENABLE_EXCEPTIONS=OFF - -DLIBCXX_ABI_NAMESPACE=__Fuzzer) + -DLIBCXX_ABI_NAMESPACE=__Fuzzer + -DLIBCXX_ENABLE_EXCEPTIONS=OFF) target_compile_options(RTfuzzer.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) add_dependencies(RTfuzzer.${arch} libcxx_fuzzer_${arch}-build) target_compile_options(RTfuzzer_main.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerBuiltinsMsvc.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerBuiltinsMsvc.h index ab191b60ef6..421dee7f660 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerBuiltinsMsvc.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerBuiltinsMsvc.h @@ -41,7 +41,8 @@ inline uint32_t Clzll(uint64_t X) { #if !defined(_M_ARM) && !defined(_M_X64) // Scan the high 32 bits. if (_BitScanReverse(&LeadZeroIdx, static_cast(X >> 32))) - return static_cast(63 - (LeadZeroIdx + 32)); // Create a bit offset from the MSB. + return static_cast( + 63 - (LeadZeroIdx + 32)); // Create a bit offset from the MSB. // Scan the low 32 bits. if (_BitScanReverse(&LeadZeroIdx, static_cast(X))) return static_cast(63 - LeadZeroIdx); diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerCommand.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerCommand.h index 87308864af5..f653fe35876 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerCommand.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerCommand.h @@ -33,7 +33,7 @@ public: Command() : CombinedOutAndErr(false) {} - explicit Command(const Vector &ArgsToAdd) + explicit Command(const std::vector &ArgsToAdd) : Args(ArgsToAdd), CombinedOutAndErr(false) {} explicit Command(const Command &Other) @@ -58,7 +58,7 @@ public: // Gets all of the current command line arguments, **including** those after // "-ignore-remaining-args=1". - const Vector &getArguments() const { return Args; } + const std::vector &getArguments() const { return Args; } // Adds the given argument before "-ignore_remaining_args=1", or at the end // if that flag isn't present. @@ -68,7 +68,7 @@ public: // Adds all given arguments before "-ignore_remaining_args=1", or at the end // if that flag isn't present. - void addArguments(const Vector &ArgsToAdd) { + void addArguments(const std::vector &ArgsToAdd) { Args.insert(endMutableArgs(), ArgsToAdd.begin(), ArgsToAdd.end()); } @@ -155,16 +155,16 @@ private: Command(Command &&Other) = delete; Command &operator=(Command &&Other) = delete; - Vector::iterator endMutableArgs() { + std::vector::iterator endMutableArgs() { return std::find(Args.begin(), Args.end(), ignoreRemainingArgs()); } - Vector::const_iterator endMutableArgs() const { + std::vector::const_iterator endMutableArgs() const { return std::find(Args.begin(), Args.end(), ignoreRemainingArgs()); } // The command arguments. Args[0] is the command name. - Vector Args; + std::vector Args; // True indicates stderr is redirected to stdout. bool CombinedOutAndErr; diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerCorpus.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerCorpus.h index f8c126072c9..e01891e18fe 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerCorpus.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerCorpus.h @@ -39,13 +39,13 @@ struct InputInfo { bool MayDeleteFile = false; bool Reduced = false; bool HasFocusFunction = false; - Vector UniqFeatureSet; - Vector DataFlowTraceForFocusFunction; + std::vector UniqFeatureSet; + std::vector DataFlowTraceForFocusFunction; // Power schedule. bool NeedsEnergyUpdate = false; double Energy = 0.0; double SumIncidence = 0.0; - Vector> FeatureFreqs; + std::vector> FeatureFreqs; // Delete feature Idx and its frequency from FeatureFreqs. bool DeleteFeatureFreq(uint32_t Idx) { @@ -209,7 +209,7 @@ public: InputInfo *AddToCorpus(const Unit &U, size_t NumFeatures, bool MayDeleteFile, bool HasFocusFunction, bool NeverReduce, std::chrono::microseconds TimeOfUnit, - const Vector &FeatureSet, + const std::vector &FeatureSet, const DataFlowTrace &DFT, const InputInfo *BaseII) { assert(!U.empty()); if (FeatureDebug) @@ -258,7 +258,7 @@ public: } // Debug-only - void PrintFeatureSet(const Vector &FeatureSet) { + void PrintFeatureSet(const std::vector &FeatureSet) { if (!FeatureDebug) return; Printf("{"); for (uint32_t Feature: FeatureSet) @@ -284,7 +284,8 @@ public: } } - void Replace(InputInfo *II, const Unit &U) { + void Replace(InputInfo *II, const Unit &U, + std::chrono::microseconds TimeOfUnit) { assert(II->U.size() > U.size()); Hashes.erase(Sha1ToString(II->Sha1)); DeleteFile(*II); @@ -292,6 +293,7 @@ public: Hashes.insert(Sha1ToString(II->Sha1)); II->U = U; II->Reduced = true; + II->TimeOfUnit = TimeOfUnit; DistributionNeedsUpdate = true; } @@ -325,7 +327,8 @@ public: const auto &II = *Inputs[i]; Printf(" [% 3zd %s] sz: % 5zd runs: % 5zd succ: % 5zd focus: %d\n", i, Sha1ToString(II.Sha1).c_str(), II.U.size(), - II.NumExecutedMutations, II.NumSuccessfullMutations, II.HasFocusFunction); + II.NumExecutedMutations, II.NumSuccessfullMutations, + II.HasFocusFunction); } } @@ -563,11 +566,11 @@ private: } std::piecewise_constant_distribution CorpusDistribution; - Vector Intervals; - Vector Weights; + std::vector Intervals; + std::vector Weights; std::unordered_set Hashes; - Vector Inputs; + std::vector Inputs; size_t NumAddedFeatures = 0; size_t NumUpdatedFeatures = 0; @@ -577,7 +580,7 @@ private: bool DistributionNeedsUpdate = true; uint16_t FreqOfMostAbundantRareFeature = 0; uint16_t GlobalFeatureFreqs[kFeatureSetSize] = {}; - Vector RareFeatures; + std::vector RareFeatures; std::string OutputCorpus; }; diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp index 23d422590d1..2f9a4d2d7ad 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp @@ -37,7 +37,7 @@ bool BlockCoverage::AppendCoverage(const std::string &S) { // Coverage lines have this form: // CN X Y Z T // where N is the number of the function, T is the total number of instrumented -// BBs, and X,Y,Z, if present, are the indecies of covered BB. +// BBs, and X,Y,Z, if present, are the indices of covered BB. // BB #0, which is the entry block, is not explicitly listed. bool BlockCoverage::AppendCoverage(std::istream &IN) { std::string L; @@ -52,7 +52,7 @@ bool BlockCoverage::AppendCoverage(std::istream &IN) { continue; } if (L[0] != 'C') continue; - Vector CoveredBlocks; + std::vector CoveredBlocks; while (true) { uint32_t BB = 0; SS >> BB; @@ -68,7 +68,7 @@ bool BlockCoverage::AppendCoverage(std::istream &IN) { auto It = Functions.find(FunctionId); auto &Counters = It == Functions.end() - ? Functions.insert({FunctionId, Vector(NumBlocks)}) + ? Functions.insert({FunctionId, std::vector(NumBlocks)}) .first->second : It->second; @@ -86,8 +86,8 @@ bool BlockCoverage::AppendCoverage(std::istream &IN) { // * any uncovered function gets weight 0. // * a function with lots of uncovered blocks gets bigger weight. // * a function with a less frequently executed code gets bigger weight. -Vector BlockCoverage::FunctionWeights(size_t NumFunctions) const { - Vector Res(NumFunctions); +std::vector BlockCoverage::FunctionWeights(size_t NumFunctions) const { + std::vector Res(NumFunctions); for (auto It : Functions) { auto FunctionID = It.first; auto Counters = It.second; @@ -104,7 +104,7 @@ Vector BlockCoverage::FunctionWeights(size_t NumFunctions) const { } void DataFlowTrace::ReadCoverage(const std::string &DirPath) { - Vector Files; + std::vector Files; GetSizedFilesFromDir(DirPath, &Files); for (auto &SF : Files) { auto Name = Basename(SF.File); @@ -115,16 +115,16 @@ void DataFlowTrace::ReadCoverage(const std::string &DirPath) { } } -static void DFTStringAppendToVector(Vector *DFT, +static void DFTStringAppendToVector(std::vector *DFT, const std::string &DFTString) { assert(DFT->size() == DFTString.size()); for (size_t I = 0, Len = DFT->size(); I < Len; I++) (*DFT)[I] = DFTString[I] == '1'; } -// converts a string of '0' and '1' into a Vector -static Vector DFTStringToVector(const std::string &DFTString) { - Vector DFT(DFTString.size()); +// converts a string of '0' and '1' into a std::vector +static std::vector DFTStringToVector(const std::string &DFTString) { + std::vector DFT(DFTString.size()); DFTStringAppendToVector(&DFT, DFTString); return DFT; } @@ -159,14 +159,14 @@ static bool ParseDFTLine(const std::string &Line, size_t *FunctionNum, } bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction, - Vector &CorporaFiles, Random &Rand) { + std::vector &CorporaFiles, Random &Rand) { if (DirPath.empty()) return false; Printf("INFO: DataFlowTrace: reading from '%s'\n", DirPath.c_str()); - Vector Files; + std::vector Files; GetSizedFilesFromDir(DirPath, &Files); std::string L; size_t FocusFuncIdx = SIZE_MAX; - Vector FunctionNames; + std::vector FunctionNames; // Collect the hashes of the corpus files. for (auto &SF : CorporaFiles) @@ -191,7 +191,7 @@ bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction, // * chooses a random function according to the weights. ReadCoverage(DirPath); auto Weights = Coverage.FunctionWeights(NumFunctions); - Vector Intervals(NumFunctions + 1); + std::vector Intervals(NumFunctions + 1); std::iota(Intervals.begin(), Intervals.end(), 0); auto Distribution = std::piecewise_constant_distribution( Intervals.begin(), Intervals.end(), Weights.begin()); @@ -247,7 +247,7 @@ bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction, } int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath, - const Vector &CorporaFiles) { + const std::vector &CorporaFiles) { Printf("INFO: collecting data flow: bin: %s dir: %s files: %zd\n", DFTBinary.c_str(), DirPath.c_str(), CorporaFiles.size()); if (CorporaFiles.empty()) { @@ -265,7 +265,7 @@ int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath, // we then request tags in [0,Size/2) and [Size/2, Size), and so on. // Function number => DFT. auto OutPath = DirPlusFile(DirPath, Hash(FileToVector(F.File))); - std::unordered_map> DFTMap; + std::unordered_map> DFTMap; std::unordered_set Cov; Command Cmd; Cmd.addArgument(DFTBinary); diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h index 07c03bb2565..054dce1bdcb 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h @@ -39,7 +39,7 @@ namespace fuzzer { int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath, - const Vector &CorporaFiles); + const std::vector &CorporaFiles); class BlockCoverage { public: @@ -77,11 +77,11 @@ public: return Result; } - Vector FunctionWeights(size_t NumFunctions) const; + std::vector FunctionWeights(size_t NumFunctions) const; void clear() { Functions.clear(); } private: - typedef Vector CoverageVector; + typedef std::vector CoverageVector; uint32_t NumberOfCoveredBlocks(const CoverageVector &Counters) const { uint32_t Res = 0; @@ -117,9 +117,9 @@ class DataFlowTrace { public: void ReadCoverage(const std::string &DirPath); bool Init(const std::string &DirPath, std::string *FocusFunction, - Vector &CorporaFiles, Random &Rand); + std::vector &CorporaFiles, Random &Rand); void Clear() { Traces.clear(); } - const Vector *Get(const std::string &InputSha1) const { + const std::vector *Get(const std::string &InputSha1) const { auto It = Traces.find(InputSha1); if (It != Traces.end()) return &It->second; @@ -128,9 +128,9 @@ class DataFlowTrace { private: // Input's sha1 => DFT for the FocusFunction. - std::unordered_map > Traces; - BlockCoverage Coverage; - std::unordered_set CorporaHashes; + std::unordered_map> Traces; + BlockCoverage Coverage; + std::unordered_set CorporaHashes; }; } // namespace fuzzer diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDefs.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDefs.h index 1a2752af2f4..db1f74a545e 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDefs.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDefs.h @@ -38,28 +38,8 @@ struct ExternalFunctions; // Global interface to functions that may or may not be available. extern ExternalFunctions *EF; -// We are using a custom allocator to give a different symbol name to STL -// containers in order to avoid ODR violations. -template - class fuzzer_allocator: public std::allocator { - public: - fuzzer_allocator() = default; - - template - fuzzer_allocator(const fuzzer_allocator&) {} - - template - struct rebind { typedef fuzzer_allocator other; }; - }; - -template -using Vector = std::vector>; - -template -using Set = std::set, fuzzer_allocator>; - -typedef Vector Unit; -typedef Vector UnitVector; +typedef std::vector Unit; +typedef std::vector UnitVector; typedef int (*UserCallback)(const uint8_t *Data, size_t Size); int FuzzerDriver(int *argc, char ***argv, UserCallback Callback); diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDictionary.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDictionary.h index db55907d936..48f063c7ee4 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDictionary.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDictionary.h @@ -52,10 +52,13 @@ class DictionaryEntry { public: DictionaryEntry() {} DictionaryEntry(Word W) : W(W) {} - DictionaryEntry(Word W, size_t PositionHint) : W(W), PositionHint(PositionHint) {} + DictionaryEntry(Word W, size_t PositionHint) + : W(W), PositionHint(PositionHint) {} const Word &GetW() const { return W; } - bool HasPositionHint() const { return PositionHint != std::numeric_limits::max(); } + bool HasPositionHint() const { + return PositionHint != std::numeric_limits::max(); + } size_t GetPositionHint() const { assert(HasPositionHint()); return PositionHint; @@ -108,12 +111,12 @@ private: }; // Parses one dictionary entry. -// If successful, write the enty to Unit and returns true, +// If successful, writes the entry to Unit and returns true, // otherwise returns false. bool ParseOneDictionaryEntry(const std::string &Str, Unit *U); // Parses the dictionary file, fills Units, returns true iff all lines // were parsed successfully. -bool ParseDictionaryFile(const std::string &Text, Vector *Units); +bool ParseDictionaryFile(const std::string &Text, std::vector *Units); } // namespace fuzzer diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDriver.cpp index ceaa9070512..6b007f2ad45 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDriver.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerDriver.cpp @@ -86,7 +86,7 @@ static const FlagDescription FlagDescriptions [] { static const size_t kNumFlags = sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]); -static Vector *Inputs; +static std::vector *Inputs; static std::string *ProgName; static void PrintHelp() { @@ -187,7 +187,7 @@ static bool ParseOneFlag(const char *Param) { } // We don't use any library to minimize dependencies. -static void ParseFlags(const Vector &Args, +static void ParseFlags(const std::vector &Args, const ExternalFunctions *EF) { for (size_t F = 0; F < kNumFlags; F++) { if (FlagDescriptions[F].IntFlag) @@ -206,7 +206,7 @@ static void ParseFlags(const Vector &Args, "Disabling -len_control by default.\n", EF->LLVMFuzzerCustomMutator); } - Inputs = new Vector; + Inputs = new std::vector; for (size_t A = 1; A < Args.size(); A++) { if (ParseOneFlag(Args[A].c_str())) { if (Flags.ignore_remaining_args) @@ -272,7 +272,7 @@ static void ValidateDirectoryExists(const std::string &Path, exit(1); } -std::string CloneArgsWithoutX(const Vector &Args, +std::string CloneArgsWithoutX(const std::vector &Args, const char *X1, const char *X2) { std::string Cmd; for (auto &S : Args) { @@ -283,18 +283,19 @@ std::string CloneArgsWithoutX(const Vector &Args, return Cmd; } -static int RunInMultipleProcesses(const Vector &Args, +static int RunInMultipleProcesses(const std::vector &Args, unsigned NumWorkers, unsigned NumJobs) { std::atomic Counter(0); std::atomic HasErrors(false); Command Cmd(Args); Cmd.removeFlag("jobs"); Cmd.removeFlag("workers"); - Vector V; + std::vector V; std::thread Pulse(PulseThread); Pulse.detach(); for (unsigned i = 0; i < NumWorkers; i++) - V.push_back(std::thread(WorkerThread, std::ref(Cmd), &Counter, NumJobs, &HasErrors)); + V.push_back(std::thread(WorkerThread, std::ref(Cmd), &Counter, NumJobs, + &HasErrors)); for (auto &T : V) T.join(); return HasErrors ? 1 : 0; @@ -348,8 +349,8 @@ static std::string GetDedupTokenFromCmdOutput(const std::string &S) { return S.substr(Beg, End - Beg); } -int CleanseCrashInput(const Vector &Args, - const FuzzingOptions &Options) { +int CleanseCrashInput(const std::vector &Args, + const FuzzingOptions &Options) { if (Inputs->size() != 1 || !Flags.exact_artifact_path) { Printf("ERROR: -cleanse_crash should be given one input file and" " -exact_artifact_path\n"); @@ -372,7 +373,7 @@ int CleanseCrashInput(const Vector &Args, auto U = FileToVector(CurrentFilePath); size_t Size = U.size(); - const Vector ReplacementBytes = {' ', 0xff}; + const std::vector ReplacementBytes = {' ', 0xff}; for (int NumAttempts = 0; NumAttempts < 5; NumAttempts++) { bool Changed = false; for (size_t Idx = 0; Idx < Size; Idx++) { @@ -403,7 +404,7 @@ int CleanseCrashInput(const Vector &Args, return 0; } -int MinimizeCrashInput(const Vector &Args, +int MinimizeCrashInput(const std::vector &Args, const FuzzingOptions &Options) { if (Inputs->size() != 1) { Printf("ERROR: -minimize_crash should be given one input file\n"); @@ -503,14 +504,15 @@ int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) { return 0; } -void Merge(Fuzzer *F, FuzzingOptions &Options, const Vector &Args, - const Vector &Corpora, const char *CFPathOrNull) { +void Merge(Fuzzer *F, FuzzingOptions &Options, + const std::vector &Args, + const std::vector &Corpora, const char *CFPathOrNull) { if (Corpora.size() < 2) { Printf("INFO: Merge requires two or more corpus dirs\n"); exit(0); } - Vector OldCorpus, NewCorpus; + std::vector OldCorpus, NewCorpus; GetSizedFilesFromDir(Corpora[0], &OldCorpus); for (size_t i = 1; i < Corpora.size(); i++) GetSizedFilesFromDir(Corpora[i], &NewCorpus); @@ -518,10 +520,10 @@ void Merge(Fuzzer *F, FuzzingOptions &Options, const Vector &Args, std::sort(NewCorpus.begin(), NewCorpus.end()); std::string CFPath = CFPathOrNull ? CFPathOrNull : TempPath("Merge", ".txt"); - Vector NewFiles; - Set NewFeatures, NewCov; + std::vector NewFiles; + std::set NewFeatures, NewCov; CrashResistantMerge(Args, OldCorpus, NewCorpus, &NewFiles, {}, &NewFeatures, - {}, &NewCov, CFPath, true); + {}, &NewCov, CFPath, true, Flags.set_cover_merge); for (auto &Path : NewFiles) F->WriteToOutputCorpus(FileToVector(Path, Options.MaxLen)); // We are done, delete the control file if it was a temporary one. @@ -531,17 +533,17 @@ void Merge(Fuzzer *F, FuzzingOptions &Options, const Vector &Args, exit(0); } -int AnalyzeDictionary(Fuzzer *F, const Vector& Dict, - UnitVector& Corpus) { +int AnalyzeDictionary(Fuzzer *F, const std::vector &Dict, + UnitVector &Corpus) { Printf("Started dictionary minimization (up to %d tests)\n", Dict.size() * Corpus.size() * 2); // Scores and usage count for each dictionary unit. - Vector Scores(Dict.size()); - Vector Usages(Dict.size()); + std::vector Scores(Dict.size()); + std::vector Usages(Dict.size()); - Vector InitialFeatures; - Vector ModifiedFeatures; + std::vector InitialFeatures; + std::vector ModifiedFeatures; for (auto &C : Corpus) { // Get coverage for the testcase without modifications. F->ExecuteCallback(C.data(), C.size()); @@ -551,7 +553,7 @@ int AnalyzeDictionary(Fuzzer *F, const Vector& Dict, }); for (size_t i = 0; i < Dict.size(); ++i) { - Vector Data = C; + std::vector Data = C; auto StartPos = std::search(Data.begin(), Data.end(), Dict[i].begin(), Dict[i].end()); // Skip dictionary unit, if the testcase does not contain it. @@ -597,9 +599,9 @@ int AnalyzeDictionary(Fuzzer *F, const Vector& Dict, return 0; } -Vector ParseSeedInuts(const char *seed_inputs) { +std::vector ParseSeedInuts(const char *seed_inputs) { // Parse -seed_inputs=file1,file2,... or -seed_inputs=@seed_inputs_file - Vector Files; + std::vector Files; if (!seed_inputs) return Files; std::string SeedInputs; if (Flags.seed_inputs[0] == '@') @@ -620,9 +622,10 @@ Vector ParseSeedInuts(const char *seed_inputs) { return Files; } -static Vector ReadCorpora(const Vector &CorpusDirs, - const Vector &ExtraSeedFiles) { - Vector SizedFiles; +static std::vector +ReadCorpora(const std::vector &CorpusDirs, + const std::vector &ExtraSeedFiles) { + std::vector SizedFiles; size_t LastNumFiles = 0; for (auto &Dir : CorpusDirs) { GetSizedFilesFromDir(Dir, &SizedFiles); @@ -645,7 +648,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { EF->LLVMFuzzerInitialize(argc, argv); if (EF->__msan_scoped_disable_interceptor_checks) EF->__msan_scoped_disable_interceptor_checks(); - const Vector Args(*argv, *argv + *argc); + const std::vector Args(*argv, *argv + *argc); assert(!Args.empty()); ProgName = new std::string(Args[0]); if (Argv0 != *ProgName) { @@ -734,7 +737,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { ValidateDirectoryExists(DirName(Options.ExactArtifactPath), Flags.create_missing_dirs); } - Vector Dictionary; + std::vector Dictionary; if (Flags.dict) if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary)) return 1; @@ -794,7 +797,8 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { if (Flags.verbosity) Printf("INFO: Seed: %u\n", Seed); - if (Flags.collect_data_flow && !Flags.fork && !Flags.merge) { + if (Flags.collect_data_flow && !Flags.fork && + !(Flags.merge || Flags.set_cover_merge)) { if (RunIndividualFiles) return CollectDataFlow(Flags.collect_data_flow, Flags.data_flow_trace, ReadCorpora({}, *Inputs)); @@ -866,10 +870,11 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { exit(0); } + Options.ForkCorpusGroups = Flags.fork_corpus_groups; if (Flags.fork) FuzzWithFork(F->GetMD().GetRand(), Options, Args, *Inputs, Flags.fork); - if (Flags.merge) + if (Flags.merge || Flags.set_cover_merge) Merge(F, Options, Args, *Inputs, Flags.merge_control_file); if (Flags.merge_inner) { @@ -877,7 +882,8 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { if (Options.MaxLen == 0) F->SetMaxInputLen(kDefaultMaxMergeLen); assert(Flags.merge_control_file); - F->CrashResistantMergeInternalStep(Flags.merge_control_file); + F->CrashResistantMergeInternalStep(Flags.merge_control_file, + !strncmp(Flags.merge_inner, "2", 1)); exit(0); } diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerExtraCounters.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerExtraCounters.cpp index 04f569a1a87..54ecbf7c62f 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerExtraCounters.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerExtraCounters.cpp @@ -31,12 +31,4 @@ void ClearExtraCounters() { // hand-written memset, don't asan-ify. } // namespace fuzzer -#else -// TODO: implement for other platforms. -namespace fuzzer { -uint8_t *ExtraCountersBegin() { return nullptr; } -uint8_t *ExtraCountersEnd() { return nullptr; } -void ClearExtraCounters() {} -} // namespace fuzzer - #endif diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerExtraCountersDarwin.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerExtraCountersDarwin.cpp new file mode 100644 index 00000000000..2321ba8a3d4 --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerExtraCountersDarwin.cpp @@ -0,0 +1,22 @@ +//===- FuzzerExtraCountersDarwin.cpp - Extra coverage counters for Darwin -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Extra coverage counters defined by user code for Darwin. +//===----------------------------------------------------------------------===// + +#include "FuzzerPlatform.h" +#include + +#if LIBFUZZER_APPLE + +namespace fuzzer { +uint8_t *ExtraCountersBegin() { return nullptr; } +uint8_t *ExtraCountersEnd() { return nullptr; } +void ClearExtraCounters() {} +} // namespace fuzzer + +#endif diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerExtraCountersWindows.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerExtraCountersWindows.cpp new file mode 100644 index 00000000000..102f5febdae --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerExtraCountersWindows.cpp @@ -0,0 +1,80 @@ +//===- FuzzerExtraCountersWindows.cpp - Extra coverage counters for Win32 -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// Extra coverage counters defined by user code for Windows. +//===----------------------------------------------------------------------===// + +#include "FuzzerPlatform.h" +#include + +#if LIBFUZZER_WINDOWS +#include + +namespace fuzzer { + +// +// The __start___libfuzzer_extra_counters variable is align 16, size 16 to +// ensure the padding between it and the next variable in this section (either +// __libfuzzer_extra_counters or __stop___libfuzzer_extra_counters) will be +// located at (__start___libfuzzer_extra_counters + +// sizeof(__start___libfuzzer_extra_counters)). Otherwise, the calculation of +// (stop - (start + sizeof(start))) might be skewed. +// +// The section name, __libfuzzer_extra_countaaa ends with "aaa", so it sorts +// before __libfuzzer_extra_counters alphabetically. We want the start symbol to +// be placed in the section just before the user supplied counters (if present). +// +#pragma section(".data$__libfuzzer_extra_countaaa") +ATTRIBUTE_ALIGNED(16) +__declspec(allocate(".data$__libfuzzer_extra_countaaa")) uint8_t + __start___libfuzzer_extra_counters[16] = {0}; + +// +// Example of what the user-supplied counters should look like. First, the +// pragma to create the section name. It will fall alphabetically between +// ".data$__libfuzzer_extra_countaaa" and ".data$__libfuzzer_extra_countzzz". +// Next, the declspec to allocate the variable inside the specified section. +// Finally, some array, struct, whatever that is used to track the counter data. +// The size of this variable is computed at runtime by finding the difference of +// __stop___libfuzzer_extra_counters and __start___libfuzzer_extra_counters + +// sizeof(__start___libfuzzer_extra_counters). +// + +// +// #pragma section(".data$__libfuzzer_extra_counters") +// __declspec(allocate(".data$__libfuzzer_extra_counters")) +// uint8_t any_name_variable[64 * 1024]; +// + +// +// Here, the section name, __libfuzzer_extra_countzzz ends with "zzz", so it +// sorts after __libfuzzer_extra_counters alphabetically. We want the stop +// symbol to be placed in the section just after the user supplied counters (if +// present). Align to 1 so there isn't any padding placed between this and the +// previous variable. +// +#pragma section(".data$__libfuzzer_extra_countzzz") +ATTRIBUTE_ALIGNED(1) +__declspec(allocate(".data$__libfuzzer_extra_countzzz")) uint8_t + __stop___libfuzzer_extra_counters = 0; + +uint8_t *ExtraCountersBegin() { + return __start___libfuzzer_extra_counters + + sizeof(__start___libfuzzer_extra_counters); +} + +uint8_t *ExtraCountersEnd() { return &__stop___libfuzzer_extra_counters; } + +ATTRIBUTE_NO_SANITIZE_ALL +void ClearExtraCounters() { + uint8_t *Beg = ExtraCountersBegin(); + SecureZeroMemory(Beg, ExtraCountersEnd() - Beg); +} + +} // namespace fuzzer + +#endif diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerFlags.def b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerFlags.def index ab31da0ae5d..11815349b01 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerFlags.def +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerFlags.def @@ -58,12 +58,21 @@ FUZZER_FLAG_INT(max_total_time, 0, "If positive, indicates the maximal total " FUZZER_FLAG_INT(help, 0, "Print help.") FUZZER_FLAG_INT(fork, 0, "Experimental mode where fuzzing happens " "in a subprocess") +FUZZER_FLAG_INT(fork_corpus_groups, 0, "For fork mode, enable the corpus-group " + "strategy, The main corpus will be grouped according to size, " + "and each sub-process will randomly select seeds from different " + "groups as the sub-corpus.") FUZZER_FLAG_INT(ignore_timeouts, 1, "Ignore timeouts in fork mode") FUZZER_FLAG_INT(ignore_ooms, 1, "Ignore OOMs in fork mode") FUZZER_FLAG_INT(ignore_crashes, 0, "Ignore crashes in fork mode") FUZZER_FLAG_INT(merge, 0, "If 1, the 2-nd, 3-rd, etc corpora will be " "merged into the 1-st corpus. Only interesting units will be taken. " "This flag can be used to minimize a corpus.") +FUZZER_FLAG_INT(set_cover_merge, 0, "If 1, the 2-nd, 3-rd, etc corpora will be " + "merged into the 1-st corpus. Same as the 'merge' flag, but uses the " + "standard greedy algorithm for the set cover problem to " + "compute an approximation of the minimum set of testcases that " + "provide the same coverage as the initial corpora") FUZZER_FLAG_STRING(stop_file, "Stop fuzzing ASAP if this file exists") FUZZER_FLAG_STRING(merge_inner, "internal flag") FUZZER_FLAG_STRING(merge_control_file, diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerFork.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerFork.cpp index 5134a5d979e..c248a1d246a 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerFork.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerFork.cpp @@ -86,18 +86,21 @@ struct FuzzJob { }; struct GlobalEnv { - Vector Args; - Vector CorpusDirs; + std::vector Args; + std::vector CorpusDirs; std::string MainCorpusDir; std::string TempDir; std::string DFTDir; std::string DataFlowBinary; - Set Features, Cov; - Set FilesWithDFT; - Vector Files; + std::set Features, Cov; + std::set FilesWithDFT; + std::vector Files; + std::vector FilesSizes; Random *Rand; std::chrono::system_clock::time_point ProcessStartTime; int Verbosity = 0; + int Group = 0; + int NumCorpuses = 8; size_t NumTimeouts = 0; size_t NumOOMs = 0; @@ -136,10 +139,24 @@ struct GlobalEnv { if (size_t CorpusSubsetSize = std::min(Files.size(), (size_t)sqrt(Files.size() + 2))) { auto Time1 = std::chrono::system_clock::now(); - for (size_t i = 0; i < CorpusSubsetSize; i++) { - auto &SF = Files[Rand->SkewTowardsLast(Files.size())]; - Seeds += (Seeds.empty() ? "" : ",") + SF; - CollectDFT(SF); + if (Group) { // whether to group the corpus. + size_t AverageCorpusSize = Files.size() / NumCorpuses + 1; + size_t StartIndex = ((JobId - 1) % NumCorpuses) * AverageCorpusSize; + for (size_t i = 0; i < CorpusSubsetSize; i++) { + size_t RandNum = (*Rand)(AverageCorpusSize); + size_t Index = RandNum + StartIndex; + Index = Index < Files.size() ? Index + : Rand->SkewTowardsLast(Files.size()); + auto &SF = Files[Index]; + Seeds += (Seeds.empty() ? "" : ",") + SF; + CollectDFT(SF); + } + } else { + for (size_t i = 0; i < CorpusSubsetSize; i++) { + auto &SF = Files[Rand->SkewTowardsLast(Files.size())]; + Seeds += (Seeds.empty() ? "" : ",") + SF; + CollectDFT(SF); + } } auto Time2 = std::chrono::system_clock::now(); auto DftTimeInSeconds = duration_cast(Time2 - Time1).count(); @@ -183,7 +200,7 @@ struct GlobalEnv { auto Stats = ParseFinalStatsFromLog(Job->LogPath); NumRuns += Stats.number_of_executed_units; - Vector TempFiles, MergeCandidates; + std::vector TempFiles, MergeCandidates; // Read all newly created inputs and their feature sets. // Choose only those inputs that have new features. GetSizedFilesFromDir(Job->CorpusDir, &TempFiles); @@ -193,7 +210,7 @@ struct GlobalEnv { FeatureFile.replace(0, Job->CorpusDir.size(), Job->FeaturesDir); auto FeatureBytes = FileToVector(FeatureFile, 0, false); assert((FeatureBytes.size() % sizeof(uint32_t)) == 0); - Vector NewFeatures(FeatureBytes.size() / sizeof(uint32_t)); + std::vector NewFeatures(FeatureBytes.size() / sizeof(uint32_t)); memcpy(NewFeatures.data(), FeatureBytes.data(), FeatureBytes.size()); for (auto Ft : NewFeatures) { if (!Features.count(Ft)) { @@ -203,7 +220,7 @@ struct GlobalEnv { } } // if (!FilesToAdd.empty() || Job->ExitCode != 0) - Printf("#%zd: cov: %zd ft: %zd corp: %zd exec/s %zd " + Printf("#%zd: cov: %zd ft: %zd corp: %zd exec/s: %zd " "oom/timeout/crash: %zd/%zd/%zd time: %zds job: %zd dft_time: %d\n", NumRuns, Cov.size(), Features.size(), Files.size(), Stats.average_exec_per_sec, NumOOMs, NumTimeouts, NumCrashes, @@ -211,15 +228,27 @@ struct GlobalEnv { if (MergeCandidates.empty()) return; - Vector FilesToAdd; - Set NewFeatures, NewCov; + std::vector FilesToAdd; + std::set NewFeatures, NewCov; + bool IsSetCoverMerge = + !Job->Cmd.getFlagValue("set_cover_merge").compare("1"); CrashResistantMerge(Args, {}, MergeCandidates, &FilesToAdd, Features, - &NewFeatures, Cov, &NewCov, Job->CFPath, false); + &NewFeatures, Cov, &NewCov, Job->CFPath, false, + IsSetCoverMerge); for (auto &Path : FilesToAdd) { auto U = FileToVector(Path); auto NewPath = DirPlusFile(MainCorpusDir, Hash(U)); WriteToFile(U, NewPath); - Files.push_back(NewPath); + if (Group) { // Insert the queue according to the size of the seed. + size_t UnitSize = U.size(); + auto Idx = + std::upper_bound(FilesSizes.begin(), FilesSizes.end(), UnitSize) - + FilesSizes.begin(); + FilesSizes.insert(FilesSizes.begin() + Idx, UnitSize); + Files.insert(Files.begin() + Idx, NewPath); + } else { + Files.push_back(NewPath); + } } Features.insert(NewFeatures.begin(), NewFeatures.end()); Cov.insert(NewCov.begin(), NewCov.end()); @@ -228,10 +257,8 @@ struct GlobalEnv { if (TPC.PcIsFuncEntry(TE)) PrintPC(" NEW_FUNC: %p %F %L\n", "", TPC.GetNextInstructionPc(TE->PC)); - } - void CollectDFT(const std::string &InputPath) { if (DataFlowBinary.empty()) return; if (!FilesWithDFT.insert(InputPath).second) return; @@ -283,8 +310,8 @@ void WorkerThread(JobQueue *FuzzQ, JobQueue *MergeQ) { // This is just a skeleton of an experimental -fork=1 feature. void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, - const Vector &Args, - const Vector &CorpusDirs, int NumJobs) { + const std::vector &Args, + const std::vector &CorpusDirs, int NumJobs) { Printf("INFO: -fork=%d: fuzzing in separate process(s)\n", NumJobs); GlobalEnv Env; @@ -294,8 +321,9 @@ void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, Env.Verbosity = Options.Verbosity; Env.ProcessStartTime = std::chrono::system_clock::now(); Env.DataFlowBinary = Options.CollectDataFlow; + Env.Group = Options.ForkCorpusGroups; - Vector SeedFiles; + std::vector SeedFiles; for (auto &Dir : CorpusDirs) GetSizedFilesFromDir(Dir, &SeedFiles); std::sort(SeedFiles.begin(), SeedFiles.end()); @@ -316,13 +344,20 @@ void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, Env.Files.push_back(File.File); } else { auto CFPath = DirPlusFile(Env.TempDir, "merge.txt"); - Set NewFeatures, NewCov; + std::set NewFeatures, NewCov; CrashResistantMerge(Env.Args, {}, SeedFiles, &Env.Files, Env.Features, - &NewFeatures, Env.Cov, &NewCov, CFPath, false); + &NewFeatures, Env.Cov, &NewCov, CFPath, + /*Verbose=*/false, /*IsSetCoverMerge=*/false); Env.Features.insert(NewFeatures.begin(), NewFeatures.end()); Env.Cov.insert(NewFeatures.begin(), NewFeatures.end()); RemoveFile(CFPath); } + + if (Env.Group) { + for (auto &path : Env.Files) + Env.FilesSizes.push_back(FileSize(path)); + } + Printf("INFO: -fork=%d: %zd seed inputs, starting to fuzz in %s\n", NumJobs, Env.Files.size(), Env.TempDir.c_str()); @@ -337,8 +372,10 @@ void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, WriteToFile(Unit({1}), Env.StopFile()); }; + size_t MergeCycle = 20; + size_t JobExecuted = 0; size_t JobId = 1; - Vector Threads; + std::vector Threads; for (int t = 0; t < NumJobs; t++) { Threads.push_back(std::thread(WorkerThread, &FuzzQ, &MergeQ)); FuzzQ.Push(Env.CreateNewJob(JobId++)); @@ -358,7 +395,46 @@ void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, Env.RunOneMergeJob(Job.get()); - // Continue if our crash is one of the ignorred ones. + // merge the corpus . + JobExecuted++; + if (Env.Group && JobExecuted >= MergeCycle) { + std::vector CurrentSeedFiles; + for (auto &Dir : CorpusDirs) + GetSizedFilesFromDir(Dir, &CurrentSeedFiles); + std::sort(CurrentSeedFiles.begin(), CurrentSeedFiles.end()); + + auto CFPath = DirPlusFile(Env.TempDir, "merge.txt"); + std::set TmpNewFeatures, TmpNewCov; + std::set TmpFeatures, TmpCov; + Env.Files.clear(); + Env.FilesSizes.clear(); + CrashResistantMerge(Env.Args, {}, CurrentSeedFiles, &Env.Files, + TmpFeatures, &TmpNewFeatures, TmpCov, &TmpNewCov, + CFPath, /*Verbose=*/false, /*IsSetCoverMerge=*/false); + for (auto &path : Env.Files) + Env.FilesSizes.push_back(FileSize(path)); + RemoveFile(CFPath); + JobExecuted = 0; + MergeCycle += 5; + } + + // Since the number of corpus seeds will gradually increase, in order to + // control the number in each group to be about three times the number of + // seeds selected each time, the number of groups is dynamically adjusted. + if (Env.Files.size() < 2000) + Env.NumCorpuses = 12; + else if (Env.Files.size() < 6000) + Env.NumCorpuses = 20; + else if (Env.Files.size() < 12000) + Env.NumCorpuses = 32; + else if (Env.Files.size() < 16000) + Env.NumCorpuses = 40; + else if (Env.Files.size() < 24000) + Env.NumCorpuses = 60; + else + Env.NumCorpuses = 80; + + // Continue if our crash is one of the ignored ones. if (Options.IgnoreTimeouts && ExitCode == Options.TimeoutExitCode) Env.NumTimeouts++; else if (Options.IgnoreOOMs && ExitCode == Options.OOMExitCode) diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerFork.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerFork.h index b29a43e13fb..fc3e9d636cb 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerFork.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerFork.h @@ -17,8 +17,8 @@ namespace fuzzer { void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, - const Vector &Args, - const Vector &CorpusDirs, int NumJobs); + const std::vector &Args, + const std::vector &CorpusDirs, int NumJobs); } // namespace fuzzer #endif // LLVM_FUZZER_FORK_H diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIO.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIO.cpp index 7f149ac6c48..0a58c5377b3 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIO.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIO.cpp @@ -23,6 +23,14 @@ namespace fuzzer { static FILE *OutputFile = stderr; +FILE *GetOutputFile() { + return OutputFile; +} + +void SetOutputFile(FILE *NewOutputFile) { + OutputFile = NewOutputFile; +} + long GetEpoch(const std::string &Path) { struct stat St; if (stat(Path.c_str(), &St)) @@ -90,11 +98,11 @@ void AppendToFile(const uint8_t *Data, size_t Size, const std::string &Path) { fclose(Out); } -void ReadDirToVectorOfUnits(const char *Path, Vector *V, long *Epoch, +void ReadDirToVectorOfUnits(const char *Path, std::vector *V, long *Epoch, size_t MaxSize, bool ExitOnError, - Vector *VPaths) { + std::vector *VPaths) { long E = Epoch ? *Epoch : 0; - Vector Files; + std::vector Files; ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true); size_t NumLoaded = 0; for (size_t i = 0; i < Files.size(); i++) { @@ -112,8 +120,8 @@ void ReadDirToVectorOfUnits(const char *Path, Vector *V, long *Epoch, } } -void GetSizedFilesFromDir(const std::string &Dir, Vector *V) { - Vector Files; +void GetSizedFilesFromDir(const std::string &Dir, std::vector *V) { + std::vector Files; ListFilesInDirRecursive(Dir, 0, &Files, /*TopDir*/true); for (auto &File : Files) if (size_t Size = FileSize(File)) diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIO.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIO.h index bde18267ea3..401afa0b447 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIO.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIO.h @@ -32,9 +32,9 @@ void WriteToFile(const Unit &U, const std::string &Path); void AppendToFile(const uint8_t *Data, size_t Size, const std::string &Path); void AppendToFile(const std::string &Data, const std::string &Path); -void ReadDirToVectorOfUnits(const char *Path, Vector *V, long *Epoch, +void ReadDirToVectorOfUnits(const char *Path, std::vector *V, long *Epoch, size_t MaxSize, bool ExitOnError, - Vector *VPaths = 0); + std::vector *VPaths = 0); // Returns "Dir/FileName" or equivalent for the current OS. std::string DirPlusFile(const std::string &DirPath, @@ -54,6 +54,10 @@ void DupAndCloseStderr(); void CloseStdout(); +// For testing. +FILE *GetOutputFile(); +void SetOutputFile(FILE *NewOutputFile); + void Printf(const char *Fmt, ...); void VPrintf(bool Verbose, const char *Fmt, ...); @@ -66,7 +70,7 @@ bool IsDirectory(const std::string &Path); size_t FileSize(const std::string &Path); void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, - Vector *V, bool TopDir); + std::vector *V, bool TopDir); bool MkDirRecursive(const std::string &Dir); void RmDirRecursive(const std::string &Dir); @@ -85,7 +89,7 @@ struct SizedFile { bool operator<(const SizedFile &B) const { return Size < B.Size; } }; -void GetSizedFilesFromDir(const std::string &Dir, Vector *V); +void GetSizedFilesFromDir(const std::string &Dir, std::vector *V); char GetSeparator(); bool IsSeparator(char C); diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIOPosix.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIOPosix.cpp index 4706a40959b..3700fb098e5 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIOPosix.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIOPosix.cpp @@ -53,7 +53,7 @@ std::string Basename(const std::string &Path) { } void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, - Vector *V, bool TopDir) { + std::vector *V, bool TopDir) { auto E = GetEpoch(Dir); if (Epoch) if (E && *Epoch >= E) return; @@ -78,7 +78,6 @@ void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, *Epoch = E; } - void IterateDirRecursive(const std::string &Dir, void (*DirPreCallback)(const std::string &Dir), void (*DirPostCallback)(const std::string &Dir), diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIOWindows.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIOWindows.cpp index 61ad35e281f..6771fc173c9 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIOWindows.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerIOWindows.cpp @@ -111,7 +111,7 @@ size_t FileSize(const std::string &Path) { } void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, - Vector *V, bool TopDir) { + std::vector *V, bool TopDir) { auto E = GetEpoch(Dir); if (Epoch) if (E && *Epoch >= E) return; @@ -159,7 +159,6 @@ void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, *Epoch = E; } - void IterateDirRecursive(const std::string &Dir, void (*DirPreCallback)(const std::string &Dir), void (*DirPostCallback)(const std::string &Dir), @@ -297,9 +296,8 @@ static size_t ParseServerAndShare(const std::string &FileName, return Pos - Offset; } -// Parse the given Ref string from the position Offset, to exactly match the given -// string Patt. -// Returns number of characters considered if successful. +// Parse the given Ref string from the position Offset, to exactly match the +// given string Patt. Returns number of characters considered if successful. static size_t ParseCustomString(const std::string &Ref, size_t Offset, const char *Patt) { size_t Len = strlen(Patt); diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerInternal.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerInternal.h index 37c8a01dc3c..a732ca87b0f 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerInternal.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerInternal.h @@ -35,8 +35,8 @@ public: Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, FuzzingOptions Options); ~Fuzzer(); - void Loop(Vector &CorporaFiles); - void ReadAndExecuteSeedCorpora(Vector &CorporaFiles); + void Loop(std::vector &CorporaFiles); + void ReadAndExecuteSeedCorpora(std::vector &CorporaFiles); void MinimizeCrashLoop(const Unit &U); void RereadOutputCorpus(size_t MaxSize); @@ -65,15 +65,19 @@ public: static void StaticFileSizeExceedCallback(); static void StaticGracefulExitCallback(); - void ExecuteCallback(const uint8_t *Data, size_t Size); + // Executes the target callback on {Data, Size} once. + // Returns false if the input was rejected by the target (target returned -1), + // and true otherwise. + bool ExecuteCallback(const uint8_t *Data, size_t Size); bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false, InputInfo *II = nullptr, bool ForceAddToCorpus = false, bool *FoundUniqFeatures = nullptr); void TPCUpdateObservedPCs(); // Merge Corpora[1:] into Corpora[0]. - void Merge(const Vector &Corpora); - void CrashResistantMergeInternalStep(const std::string &ControlFilePath); + void Merge(const std::vector &Corpora); + void CrashResistantMergeInternalStep(const std::string &ControlFilePath, + bool IsSetCoverMerge); MutationDispatcher &GetMD() { return MD; } void PrintFinalStats(); void SetMaxInputLen(size_t MaxInputLen); @@ -87,6 +91,7 @@ public: void HandleMalloc(size_t Size); static void MaybeExitGracefully(); + static int InterruptExitCode(); std::string WriteToOutputCorpus(const Unit &U); private: @@ -141,7 +146,7 @@ private: size_t MaxMutationLen = 0; size_t TmpMaxMutationLen = 0; - Vector UniqFeatureSetTmp; + std::vector UniqFeatureSetTmp; // Need to know our own thread. static thread_local bool IsMyThread; diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerLoop.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerLoop.cpp index 86a78ab7517..00f5ed7743b 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerLoop.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerLoop.cpp @@ -262,6 +262,11 @@ void Fuzzer::MaybeExitGracefully() { _Exit(0); } +int Fuzzer::InterruptExitCode() { + assert(F); + return F->Options.InterruptExitCode; +} + void Fuzzer::InterruptCallback() { Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid()); PrintFinalStats(); @@ -388,7 +393,7 @@ void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) { void Fuzzer::CheckExitOnSrcPosOrItem() { if (!Options.ExitOnSrcPos.empty()) { - static auto *PCsSet = new Set; + static auto *PCsSet = new std::set; auto HandlePC = [&](const TracePC::PCTableEntry *TE) { if (!PCsSet->insert(TE->PC).second) return; @@ -413,8 +418,8 @@ void Fuzzer::CheckExitOnSrcPosOrItem() { void Fuzzer::RereadOutputCorpus(size_t MaxSize) { if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec) return; - Vector AdditionalCorpus; - Vector AdditionalCorpusPaths; + std::vector AdditionalCorpus; + std::vector AdditionalCorpusPaths; ReadDirToVectorOfUnits( Options.OutputCorpus.c_str(), &AdditionalCorpus, &EpochOfLastReadOfOutputCorpus, MaxSize, @@ -457,7 +462,7 @@ void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) { static void WriteFeatureSetToFile(const std::string &FeaturesDir, const std::string &FileName, - const Vector &FeatureSet) { + const std::vector &FeatureSet) { if (FeaturesDir.empty() || FeatureSet.empty()) return; WriteToFile(reinterpret_cast(FeatureSet.data()), FeatureSet.size() * sizeof(FeatureSet[0]), @@ -511,7 +516,7 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile, // Largest input length should be INT_MAX. assert(Size < std::numeric_limits::max()); - ExecuteCallback(Data, Size); + if(!ExecuteCallback(Data, Size)) return false; auto TimeOfUnit = duration_cast(UnitStopTime - UnitStartTime); UniqFeatureSetTmp.clear(); @@ -548,7 +553,7 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile, FoundUniqFeaturesOfII == II->UniqFeatureSet.size() && II->U.size() > Size) { auto OldFeaturesFile = Sha1ToString(II->Sha1); - Corpus.Replace(II, {Data, Data + Size}); + Corpus.Replace(II, {Data, Data + Size}, TimeOfUnit); RenameFeatureSetFile(Options.FeaturesDir, OldFeaturesFile, Sha1ToString(II->Sha1)); return true; @@ -586,7 +591,7 @@ static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) { // This method is not inlined because it would cause a test to fail where it // is part of the stack unwinding. See D97975 for details. -ATTRIBUTE_NOINLINE void Fuzzer::ExecuteCallback(const uint8_t *Data, +ATTRIBUTE_NOINLINE bool Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) { TPC.RecordInitialStack(); TotalNumberOfRuns++; @@ -602,23 +607,24 @@ ATTRIBUTE_NOINLINE void Fuzzer::ExecuteCallback(const uint8_t *Data, if (CurrentUnitData && CurrentUnitData != Data) memcpy(CurrentUnitData, Data, Size); CurrentUnitSize = Size; + int CBRes = 0; { ScopedEnableMsanInterceptorChecks S; AllocTracer.Start(Options.TraceMalloc); UnitStartTime = system_clock::now(); TPC.ResetMaps(); RunningUserCallback = true; - int Res = CB(DataCopy, Size); + CBRes = CB(DataCopy, Size); RunningUserCallback = false; UnitStopTime = system_clock::now(); - (void)Res; - assert(Res == 0); + assert(CBRes == 0 || CBRes == -1); HasMoreMallocsThanFrees = AllocTracer.Stop(); } if (!LooseMemeq(DataCopy, Data, Size)) CrashOnOverwrittenData(); CurrentUnitSize = 0; delete[] DataCopy; + return CBRes == 0; } std::string Fuzzer::WriteToOutputCorpus(const Unit &U) { @@ -784,7 +790,7 @@ void Fuzzer::PurgeAllocator() { LastAllocatorPurgeAttemptTime = system_clock::now(); } -void Fuzzer::ReadAndExecuteSeedCorpora(Vector &CorporaFiles) { +void Fuzzer::ReadAndExecuteSeedCorpora(std::vector &CorporaFiles) { const size_t kMaxSaneLen = 1 << 20; const size_t kMinDefaultLen = 4096; size_t MaxSize = 0; @@ -843,13 +849,20 @@ void Fuzzer::ReadAndExecuteSeedCorpora(Vector &CorporaFiles) { } if (Corpus.empty() && Options.MaxNumberOfRuns) { - Printf("ERROR: no interesting inputs were found. " - "Is the code instrumented for coverage? Exiting.\n"); - exit(1); + Printf("WARNING: no interesting inputs were found so far. " + "Is the code instrumented for coverage?\n" + "This may also happen if the target rejected all inputs we tried so " + "far\n"); + // The remaining logic requires that the corpus is not empty, + // so we add one fake input to the in-memory corpus. + Corpus.AddToCorpus({'\n'}, /*NumFeatures=*/1, /*MayDeleteFile=*/true, + /*HasFocusFunction=*/false, /*NeverReduce=*/false, + /*TimeOfUnit=*/duration_cast(0s), {0}, DFT, + /*BaseII*/ nullptr); } } -void Fuzzer::Loop(Vector &CorporaFiles) { +void Fuzzer::Loop(std::vector &CorporaFiles) { auto FocusFunctionOrAuto = Options.FocusFunction; DFT.Init(Options.DataFlowTrace, &FocusFunctionOrAuto, CorporaFiles, MD.GetRand()); diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMerge.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMerge.cpp index 162453ceae2..24bd11958e8 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMerge.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMerge.cpp @@ -77,8 +77,8 @@ bool Merger::Parse(std::istream &IS, bool ParseCoverage) { size_t ExpectedStartMarker = 0; const size_t kInvalidStartMarker = -1; size_t LastSeenStartMarker = kInvalidStartMarker; - Vector TmpFeatures; - Set PCs; + std::vector TmpFeatures; + std::set PCs; while (std::getline(IS, Line, '\n')) { std::istringstream ISS1(Line); std::string Marker; @@ -132,15 +132,16 @@ size_t Merger::ApproximateMemoryConsumption() const { // Decides which files need to be merged (add those to NewFiles). // Returns the number of new features added. -size_t Merger::Merge(const Set &InitialFeatures, - Set *NewFeatures, - const Set &InitialCov, Set *NewCov, - Vector *NewFiles) { +size_t Merger::Merge(const std::set &InitialFeatures, + std::set *NewFeatures, + const std::set &InitialCov, + std::set *NewCov, + std::vector *NewFiles) { NewFiles->clear(); NewFeatures->clear(); NewCov->clear(); assert(NumFilesInFirstCorpus <= Files.size()); - Set AllFeatures = InitialFeatures; + std::set AllFeatures = InitialFeatures; // What features are in the initial corpus? for (size_t i = 0; i < NumFilesInFirstCorpus; i++) { @@ -150,7 +151,7 @@ size_t Merger::Merge(const Set &InitialFeatures, // Remove all features that we already know from all other inputs. for (size_t i = NumFilesInFirstCorpus; i < Files.size(); i++) { auto &Cur = Files[i].Features; - Vector Tmp; + std::vector Tmp; std::set_difference(Cur.begin(), Cur.end(), AllFeatures.begin(), AllFeatures.end(), std::inserter(Tmp, Tmp.begin())); Cur.swap(Tmp); @@ -188,15 +189,16 @@ size_t Merger::Merge(const Set &InitialFeatures, return NewFeatures->size(); } -Set Merger::AllFeatures() const { - Set S; +std::set Merger::AllFeatures() const { + std::set S; for (auto &File : Files) S.insert(File.Features.begin(), File.Features.end()); return S; } // Inner process. May crash if the target crashes. -void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) { +void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath, + bool IsSetCoverMerge) { Printf("MERGE-INNER: using the control file '%s'\n", CFPath.c_str()); Merger M; std::ifstream IF(CFPath); @@ -212,11 +214,11 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) { M.Files.size() - M.FirstNotProcessedFile); std::ofstream OF(CFPath, std::ofstream::out | std::ofstream::app); - Set AllFeatures; + std::set AllFeatures; auto PrintStatsWrapper = [this, &AllFeatures](const char* Where) { this->PrintStats(Where, "\n", 0, AllFeatures.size()); }; - Set AllPCs; + std::set AllPCs; for (size_t i = M.FirstNotProcessedFile; i < M.Files.size(); i++) { Fuzzer::MaybeExitGracefully(); auto U = FileToVector(M.Files[i].Name); @@ -234,13 +236,14 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) { // Collect coverage. We are iterating over the files in this order: // * First, files in the initial corpus ordered by size, smallest first. // * Then, all other files, smallest first. - // So it makes no sense to record all features for all files, instead we - // only record features that were not seen before. - Set UniqFeatures; - TPC.CollectFeatures([&](size_t Feature) { - if (AllFeatures.insert(Feature).second) - UniqFeatures.insert(Feature); - }); + std::set Features; + if (IsSetCoverMerge) + TPC.CollectFeatures([&](size_t Feature) { Features.insert(Feature); }); + else + TPC.CollectFeatures([&](size_t Feature) { + if (AllFeatures.insert(Feature).second) + Features.insert(Feature); + }); TPC.UpdateObservedPCs(); // Show stats. if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1))) @@ -249,7 +252,7 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) { PrintStatsWrapper("LOADED"); // Write the post-run marker and the coverage. OF << "FT " << i; - for (size_t F : UniqFeatures) + for (size_t F : Features) OF << " " << F; OF << "\n"; OF << "COV " << i; @@ -263,15 +266,137 @@ void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) { PrintStatsWrapper("DONE "); } -static size_t WriteNewControlFile(const std::string &CFPath, - const Vector &OldCorpus, - const Vector &NewCorpus, - const Vector &KnownFiles) { +// Merges all corpora into the first corpus. A file is added into +// the first corpus only if it adds new features. Unlike `Merger::Merge`, +// this implementation calculates an approximation of the minimum set +// of corpora files, that cover all known features (set cover problem). +// Generally, this means that files with more features are preferred for +// merge into the first corpus. When two files have the same number of +// features, the smaller one is preferred. +size_t Merger::SetCoverMerge(const std::set &InitialFeatures, + std::set *NewFeatures, + const std::set &InitialCov, + std::set *NewCov, + std::vector *NewFiles) { + assert(NumFilesInFirstCorpus <= Files.size()); + NewFiles->clear(); + NewFeatures->clear(); + NewCov->clear(); + std::set AllFeatures; + // 1 << 21 - 1 is the maximum feature index. + // See 'kFeatureSetSize' in 'FuzzerCorpus.h'. + const uint32_t kFeatureSetSize = 1 << 21; + std::vector Covered(kFeatureSetSize, false); + size_t NumCovered = 0; + + std::set ExistingFeatures = InitialFeatures; + for (size_t i = 0; i < NumFilesInFirstCorpus; ++i) + ExistingFeatures.insert(Files[i].Features.begin(), Files[i].Features.end()); + + // Mark the existing features as covered. + for (const auto &F : ExistingFeatures) { + if (!Covered[F % kFeatureSetSize]) { + ++NumCovered; + Covered[F % kFeatureSetSize] = true; + } + // Calculate an underestimation of the set of covered features + // since the `Covered` bitvector is smaller than the feature range. + AllFeatures.insert(F % kFeatureSetSize); + } + + std::set RemainingFiles; + for (size_t i = NumFilesInFirstCorpus; i < Files.size(); ++i) { + // Construct an incremental sequence which represent the + // indices to all files (excluding those in the initial corpus). + // RemainingFiles = range(NumFilesInFirstCorpus..Files.size()). + RemainingFiles.insert(i); + // Insert this file's unique features to all features. + for (const auto &F : Files[i].Features) + AllFeatures.insert(F % kFeatureSetSize); + } + + // Integrate files into Covered until set is complete. + while (NumCovered != AllFeatures.size()) { + // Index to file with largest number of unique features. + size_t MaxFeaturesIndex = NumFilesInFirstCorpus; + // Indices to remove from RemainingFiles. + std::set RemoveIndices; + // Running max unique feature count. + // Updated upon finding a file with more features. + size_t MaxNumFeatures = 0; + + // Iterate over all files not yet integrated into Covered, + // to find the file which has the largest number of + // features that are not already in Covered. + for (const auto &i : RemainingFiles) { + const auto &File = Files[i]; + size_t CurrentUnique = 0; + // Count number of features in this file + // which are not yet in Covered. + for (const auto &F : File.Features) + if (!Covered[F % kFeatureSetSize]) + ++CurrentUnique; + + if (CurrentUnique == 0) { + // All features in this file are already in Covered: skip next time. + RemoveIndices.insert(i); + } else if (CurrentUnique > MaxNumFeatures || + (CurrentUnique == MaxNumFeatures && + File.Size < Files[MaxFeaturesIndex].Size)) { + // Update the max features file based on unique features + // Break ties by selecting smaller files. + MaxNumFeatures = CurrentUnique; + MaxFeaturesIndex = i; + } + } + // Must be a valid index/ + assert(MaxFeaturesIndex < Files.size()); + // Remove any feature-less files found. + for (const auto &i : RemoveIndices) + RemainingFiles.erase(i); + if (MaxNumFeatures == 0) { + // Did not find a file that adds unique features. + // This means that we should have no remaining files. + assert(RemainingFiles.size() == 0); + assert(NumCovered == AllFeatures.size()); + break; + } + + // MaxFeaturesIndex must be an element of Remaining. + assert(RemainingFiles.find(MaxFeaturesIndex) != RemainingFiles.end()); + // Remove the file with the most features from Remaining. + RemainingFiles.erase(MaxFeaturesIndex); + const auto &MaxFeatureFile = Files[MaxFeaturesIndex]; + // Add the features of the max feature file to Covered. + for (const auto &F : MaxFeatureFile.Features) { + if (!Covered[F % kFeatureSetSize]) { + ++NumCovered; + Covered[F % kFeatureSetSize] = true; + NewFeatures->insert(F); + } + } + // Add the index to this file to the result. + NewFiles->push_back(MaxFeatureFile.Name); + // Update NewCov with the additional coverage + // that MaxFeatureFile provides. + for (const auto &C : MaxFeatureFile.Cov) + if (InitialCov.find(C) == InitialCov.end()) + NewCov->insert(C); + } + + return NewFeatures->size(); +} + +static size_t +WriteNewControlFile(const std::string &CFPath, + const std::vector &OldCorpus, + const std::vector &NewCorpus, + const std::vector &KnownFiles) { std::unordered_set FilesToSkip; for (auto &SF: KnownFiles) FilesToSkip.insert(SF.Name); - Vector FilesToUse; + std::vector FilesToUse; auto MaybeUseFile = [=, &FilesToUse](std::string Name) { if (FilesToSkip.find(Name) == FilesToSkip.end()) FilesToUse.push_back(Name); @@ -299,19 +424,19 @@ static size_t WriteNewControlFile(const std::string &CFPath, } // Outer process. Does not call the target code and thus should not fail. -void CrashResistantMerge(const Vector &Args, - const Vector &OldCorpus, - const Vector &NewCorpus, - Vector *NewFiles, - const Set &InitialFeatures, - Set *NewFeatures, - const Set &InitialCov, - Set *NewCov, - const std::string &CFPath, - bool V /*Verbose*/) { +void CrashResistantMerge(const std::vector &Args, + const std::vector &OldCorpus, + const std::vector &NewCorpus, + std::vector *NewFiles, + const std::set &InitialFeatures, + std::set *NewFeatures, + const std::set &InitialCov, + std::set *NewCov, const std::string &CFPath, + bool V, /*Verbose*/ + bool IsSetCoverMerge) { if (NewCorpus.empty() && OldCorpus.empty()) return; // Nothing to merge. size_t NumAttempts = 0; - Vector KnownFiles; + std::vector KnownFiles; if (FileSize(CFPath)) { VPrintf(V, "MERGE-OUTER: non-empty control file provided: '%s'\n", CFPath.c_str()); @@ -363,6 +488,7 @@ void CrashResistantMerge(const Vector &Args, // Every inner process should execute at least one input. Command BaseCmd(Args); BaseCmd.removeFlag("merge"); + BaseCmd.removeFlag("set_cover_merge"); BaseCmd.removeFlag("fork"); BaseCmd.removeFlag("collect_data_flow"); for (size_t Attempt = 1; Attempt <= NumAttempts; Attempt++) { @@ -370,14 +496,16 @@ void CrashResistantMerge(const Vector &Args, VPrintf(V, "MERGE-OUTER: attempt %zd\n", Attempt); Command Cmd(BaseCmd); Cmd.addFlag("merge_control_file", CFPath); - Cmd.addFlag("merge_inner", "1"); + // If we are going to use the set cover implementation for + // minimization add the merge_inner=2 internal flag. + Cmd.addFlag("merge_inner", IsSetCoverMerge ? "2" : "1"); if (!V) { Cmd.setOutputFile(getDevNull()); Cmd.combineOutAndErr(); } auto ExitCode = ExecuteCommand(Cmd); if (!ExitCode) { - VPrintf(V, "MERGE-OUTER: succesfull in %zd attempt(s)\n", Attempt); + VPrintf(V, "MERGE-OUTER: successful in %zd attempt(s)\n", Attempt); break; } } @@ -395,7 +523,10 @@ void CrashResistantMerge(const Vector &Args, M.ApproximateMemoryConsumption() >> 20, GetPeakRSSMb()); M.Files.insert(M.Files.end(), KnownFiles.begin(), KnownFiles.end()); - M.Merge(InitialFeatures, NewFeatures, InitialCov, NewCov, NewFiles); + if (IsSetCoverMerge) + M.SetCoverMerge(InitialFeatures, NewFeatures, InitialCov, NewCov, NewFiles); + else + M.Merge(InitialFeatures, NewFeatures, InitialCov, NewCov, NewFiles); VPrintf(V, "MERGE-OUTER: %zd new files with %zd new features added; " "%zd new coverage edges\n", NewFiles->size(), NewFeatures->size(), NewCov->size()); diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMerge.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMerge.h index e0c6bc539bd..42f798e1da1 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMerge.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMerge.h @@ -41,6 +41,7 @@ #define LLVM_FUZZER_MERGE_H #include "FuzzerDefs.h" +#include "FuzzerIO.h" #include #include @@ -52,11 +53,11 @@ namespace fuzzer { struct MergeFileInfo { std::string Name; size_t Size = 0; - Vector Features, Cov; + std::vector Features, Cov; }; struct Merger { - Vector Files; + std::vector Files; size_t NumFilesInFirstCorpus = 0; size_t FirstNotProcessedFile = 0; std::string LastFailure; @@ -64,23 +65,28 @@ struct Merger { bool Parse(std::istream &IS, bool ParseCoverage); bool Parse(const std::string &Str, bool ParseCoverage); void ParseOrExit(std::istream &IS, bool ParseCoverage); - size_t Merge(const Set &InitialFeatures, Set *NewFeatures, - const Set &InitialCov, Set *NewCov, - Vector *NewFiles); + size_t Merge(const std::set &InitialFeatures, + std::set *NewFeatures, + const std::set &InitialCov, std::set *NewCov, + std::vector *NewFiles); + size_t SetCoverMerge(const std::set &InitialFeatures, + std::set *NewFeatures, + const std::set &InitialCov, + std::set *NewCov, + std::vector *NewFiles); size_t ApproximateMemoryConsumption() const; - Set AllFeatures() const; + std::set AllFeatures() const; }; -void CrashResistantMerge(const Vector &Args, - const Vector &OldCorpus, - const Vector &NewCorpus, - Vector *NewFiles, - const Set &InitialFeatures, - Set *NewFeatures, - const Set &InitialCov, - Set *NewCov, - const std::string &CFPath, - bool Verbose); +void CrashResistantMerge(const std::vector &Args, + const std::vector &OldCorpus, + const std::vector &NewCorpus, + std::vector *NewFiles, + const std::set &InitialFeatures, + std::set *NewFeatures, + const std::set &InitialCov, + std::set *NewCov, const std::string &CFPath, + bool Verbose, bool IsSetCoverMerge); } // namespace fuzzer diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMutate.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMutate.cpp index 4650f1becea..d663900fdc3 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMutate.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMutate.cpp @@ -485,7 +485,7 @@ void MutationDispatcher::RecordSuccessfulMutationSequence() { } void MutationDispatcher::PrintRecommendedDictionary() { - Vector V; + std::vector V; for (auto &DE : PersistentAutoDictionary) if (!ManualDictionary.ContainsWord(DE.GetW())) V.push_back(DE); @@ -540,7 +540,7 @@ size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size, // Mutates Data in place, returns new size. size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize, - Vector &Mutators) { + std::vector &Mutators) { assert(MaxSize > 0); // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize), // in which case they will return 0. @@ -562,7 +562,7 @@ size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size, // Mask represents the set of Data bytes that are worth mutating. size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size, size_t MaxSize, - const Vector &Mask) { + const std::vector &Mask) { size_t MaskedSize = std::min(Size, Mask.size()); // * Copy the worthy bytes into a temporary array T // * Mutate T diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMutate.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMutate.h index fd37191156d..97704e2160a 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMutate.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerMutate.h @@ -77,7 +77,7 @@ public: /// that have '1' in Mask. /// Mask.size() should be >= Size. size_t MutateWithMask(uint8_t *Data, size_t Size, size_t MaxSize, - const Vector &Mask); + const std::vector &Mask); /// Applies one of the default mutations. Provided as a service /// to mutation authors. @@ -104,7 +104,7 @@ public: size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size, size_t MaxSize); size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize, - Vector &Mutators); + std::vector &Mutators); size_t InsertPartOf(const uint8_t *From, size_t FromSize, uint8_t *To, size_t ToSize, size_t MaxToSize); @@ -133,22 +133,22 @@ public: // entries that led to successful discoveries in the past mutations. Dictionary PersistentAutoDictionary; - Vector CurrentDictionaryEntrySequence; + std::vector CurrentDictionaryEntrySequence; static const size_t kCmpDictionaryEntriesDequeSize = 16; DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize]; size_t CmpDictionaryEntriesDequeIdx = 0; const Unit *CrossOverWith = nullptr; - Vector MutateInPlaceHere; - Vector MutateWithMaskTemp; + std::vector MutateInPlaceHere; + std::vector MutateWithMaskTemp; // CustomCrossOver needs its own buffer as a custom implementation may call // LLVMFuzzerMutate, which in turn may resize MutateInPlaceHere. - Vector CustomCrossOverInPlaceHere; + std::vector CustomCrossOverInPlaceHere; - Vector Mutators; - Vector DefaultMutators; - Vector CurrentMutatorSequence; + std::vector Mutators; + std::vector DefaultMutators; + std::vector CurrentMutatorSequence; }; } // namespace fuzzer diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerOptions.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerOptions.h index d0c285a6821..72e25610619 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerOptions.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerOptions.h @@ -47,6 +47,7 @@ struct FuzzingOptions { int ReportSlowUnits = 10; bool OnlyASCII = false; bool Entropic = true; + bool ForkCorpusGroups = false; size_t EntropicFeatureFrequencyThreshold = 0xFF; size_t EntropicNumberOfRarestFeatures = 100; bool EntropicScalePerExecTime = false; diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp index d808b9b00fa..f12f7aa61bc 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp @@ -133,13 +133,14 @@ inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) { // so we return (pc-2) in that case in order to be safe. // For A32 mode we return (pc-4) because all instructions are 32 bit long. return (PC - 3) & (~1); -#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__) - // PCs are always 4 byte aligned. - return PC - 4; #elif defined(__sparc__) || defined(__mips__) return PC - 8; -#else +#elif defined(__riscv__) + return PC - 2; +#elif defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) return PC - 1; +#else + return PC - 4; #endif } @@ -157,7 +158,7 @@ ALWAYS_INLINE uintptr_t TracePC::GetNextInstructionPc(uintptr_t PC) { } void TracePC::UpdateObservedPCs() { - Vector CoveredFuncs; + std::vector CoveredFuncs; auto ObservePC = [&](const PCTableEntry *TE) { if (ObservedPCs.insert(TE).second && DoPrintNewPCs) { PrintPC("\tNEW_PC: %p %F %L", "\tNEW_PC: %p", @@ -300,8 +301,8 @@ void TracePC::PrintCoverage(bool PrintAllCounters) { FunctionStr = FunctionStr.substr(3); std::string LineStr = DescribePC("%l", VisualizePC); size_t NumEdges = Last - First; - Vector UncoveredPCs; - Vector CoveredPCs; + std::vector UncoveredPCs; + std::vector CoveredPCs; for (auto TE = First; TE < Last; TE++) if (!ObservedPCs.count(TE)) UncoveredPCs.push_back(TE->PC); @@ -391,6 +392,7 @@ void TracePC::HandleCmp(uintptr_t PC, T Arg1, T Arg2) { ValueProfileMap.AddValue(PC * 128 + 64 + AbsoluteDistance); } +ATTRIBUTE_NO_SANITIZE_MEMORY static size_t InternalStrnlen(const char *S, size_t MaxLen) { size_t Len = 0; for (; Len < MaxLen && S[Len]; Len++) {} @@ -398,7 +400,8 @@ static size_t InternalStrnlen(const char *S, size_t MaxLen) { } // Finds min of (strlen(S1), strlen(S2)). -// Needed bacause one of these strings may actually be non-zero terminated. +// Needed because one of these strings may actually be non-zero terminated. +ATTRIBUTE_NO_SANITIZE_MEMORY static size_t InternalStrnlen2(const char *S1, const char *S2) { size_t Len = 0; for (; S1[Len] && S2[Len]; Len++) {} diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerTracePC.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerTracePC.h index a93732972f7..af1f9d81e95 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerTracePC.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerTracePC.h @@ -169,7 +169,7 @@ private: size_t NumPCTables; size_t NumPCsInPCTables; - Set ObservedPCs; + std::set ObservedPCs; std::unordered_map ObservedFuncs; // PC => Counter. uint8_t *FocusFunctionCounterPtr = nullptr; diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtil.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtil.cpp index 05185499bdd..aeab70f20c2 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtil.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtil.cpp @@ -43,7 +43,7 @@ void PrintASCIIByte(uint8_t Byte) { else if (Byte >= 32 && Byte < 127) Printf("%c", Byte); else - Printf("\\x%02x", Byte); + Printf("\\%03o", Byte); } void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter) { @@ -124,7 +124,7 @@ bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) { return true; } -bool ParseDictionaryFile(const std::string &Text, Vector *Units) { +bool ParseDictionaryFile(const std::string &Text, std::vector *Units) { if (Text.empty()) { Printf("ParseDictionaryFile: file does not exist or is empty\n"); return false; diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtil.h b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtil.h index a188a7be32a..71d49097e55 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtil.h +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtil.h @@ -66,10 +66,10 @@ int CloseProcessPipe(FILE *F); const void *SearchMemory(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen); -std::string CloneArgsWithoutX(const Vector &Args, +std::string CloneArgsWithoutX(const std::vector &Args, const char *X1, const char *X2); -inline std::string CloneArgsWithoutX(const Vector &Args, +inline std::string CloneArgsWithoutX(const std::vector &Args, const char *X) { return CloneArgsWithoutX(Args, X, X); } diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp index 5034b4a28d3..d80b80cccb8 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp @@ -52,6 +52,12 @@ void CrashTrampolineAsm() __asm__("CrashTrampolineAsm"); namespace { +// The signal handler thread uses Zircon exceptions to resume crashed threads +// into libFuzzer's POSIX signal handlers. The associated event is used to +// signal when the thread is running, and when it should stop. +std::thread SignalHandler; +zx_handle_t SignalHandlerEvent = ZX_HANDLE_INVALID; + // Helper function to handle Zircon syscall failures. void ExitOnErr(zx_status_t Status, const char *Syscall) { if (Status != ZX_OK) { @@ -68,23 +74,6 @@ void AlarmHandler(int Seconds) { } } -// CFAOffset is used to reference the stack pointer before entering the -// trampoline (Stack Pointer + CFAOffset = prev Stack Pointer). Before jumping -// to the trampoline we copy all the registers onto the stack. We need to make -// sure that the new stack has enough space to store all the registers. -// -// The trampoline holds CFI information regarding the registers stored in the -// stack, which is then used by the unwinder to restore them. -#if defined(__x86_64__) -// In x86_64 the crashing function might also be using the red zone (128 bytes -// on top of their rsp). -constexpr size_t CFAOffset = 128 + sizeof(zx_thread_state_general_regs_t); -#elif defined(__aarch64__) -// In aarch64 we need to always have the stack pointer aligned to 16 bytes, so we -// make sure that we are keeping that same alignment. -constexpr size_t CFAOffset = (sizeof(zx_thread_state_general_regs_t) + 15) & -(uintptr_t)16; -#endif - // For the crash handler, we need to call Fuzzer::StaticCrashSignalCallback // without POSIX signal handlers. To achieve this, we use an assembly function // to add the necessary CFI unwinding information and a C function to bridge @@ -163,10 +152,10 @@ constexpr size_t CFAOffset = (sizeof(zx_thread_state_general_regs_t) + 15) & -(u // Produces an assembler immediate operand for the named or numbered register. // This operand contains the offset of the register relative to the CFA. -#define ASM_OPERAND_REG(reg) \ - [reg] "i"(offsetof(zx_thread_state_general_regs_t, reg) - CFAOffset), -#define ASM_OPERAND_NUM(num) \ - [x##num] "i"(offsetof(zx_thread_state_general_regs_t, r[num]) - CFAOffset), +#define ASM_OPERAND_REG(reg) \ + [reg] "i"(offsetof(zx_thread_state_general_regs_t, reg)), +#define ASM_OPERAND_NUM(num) \ + [x##num] "i"(offsetof(zx_thread_state_general_regs_t, r[num])), // Trampoline to bridge from the assembly below to the static C++ crash // callback. @@ -178,62 +167,57 @@ static void StaticCrashHandler() { } } -// Creates the trampoline with the necessary CFI information to unwind through -// to the crashing call stack: -// * Defining the CFA so that it points to the stack pointer at the point -// of crash. -// * Storing all registers at the point of crash in the stack and refer to them -// via CFI information (relative to the CFA). -// * Setting the return column so the unwinder knows how to continue unwinding. -// * (x86_64) making sure rsp is aligned before calling StaticCrashHandler. -// * Calling StaticCrashHandler that will trigger the unwinder. +// This trampoline function has the necessary CFI information to unwind +// and get a backtrace: +// * The stack contains a copy of all the registers at the point of crash, +// the code has CFI directives specifying how to restore them. +// * A call to StaticCrashHandler, which will print the stacktrace and exit +// the fuzzer, generating a crash artifact. // // The __attribute__((used)) is necessary because the function // is never called; it's just a container around the assembly to allow it to // use operands for compile-time computed constants. __attribute__((used)) void MakeTrampoline() { - __asm__(".cfi_endproc\n" - ".pushsection .text.CrashTrampolineAsm\n" - ".type CrashTrampolineAsm,STT_FUNC\n" -"CrashTrampolineAsm:\n" - ".cfi_startproc simple\n" - ".cfi_signal_frame\n" + __asm__( + ".cfi_endproc\n" + ".pushsection .text.CrashTrampolineAsm\n" + ".type CrashTrampolineAsm,STT_FUNC\n" + "CrashTrampolineAsm:\n" + ".cfi_startproc simple\n" + ".cfi_signal_frame\n" #if defined(__x86_64__) - ".cfi_return_column rip\n" - ".cfi_def_cfa rsp, %c[CFAOffset]\n" - FOREACH_REGISTER(CFI_OFFSET_REG, CFI_OFFSET_NUM) - "mov %%rsp, %%rbp\n" - ".cfi_def_cfa_register rbp\n" - "andq $-16, %%rsp\n" - "call %c[StaticCrashHandler]\n" - "ud2\n" + ".cfi_return_column rip\n" + ".cfi_def_cfa rsp, 0\n" + FOREACH_REGISTER(CFI_OFFSET_REG, CFI_OFFSET_NUM) + "call %c[StaticCrashHandler]\n" + "ud2\n" #elif defined(__aarch64__) - ".cfi_return_column 33\n" - ".cfi_def_cfa sp, %c[CFAOffset]\n" - FOREACH_REGISTER(CFI_OFFSET_REG, CFI_OFFSET_NUM) - ".cfi_offset 33, %c[pc]\n" - ".cfi_offset 30, %c[lr]\n" - "bl %c[StaticCrashHandler]\n" - "brk 1\n" + ".cfi_return_column 33\n" + ".cfi_def_cfa sp, 0\n" + FOREACH_REGISTER(CFI_OFFSET_REG, CFI_OFFSET_NUM) + ".cfi_offset 33, %c[pc]\n" + ".cfi_offset 30, %c[lr]\n" + "bl %c[StaticCrashHandler]\n" + "brk 1\n" #else #error "Unsupported architecture for fuzzing on Fuchsia" #endif - ".cfi_endproc\n" - ".size CrashTrampolineAsm, . - CrashTrampolineAsm\n" - ".popsection\n" - ".cfi_startproc\n" - : // No outputs - : FOREACH_REGISTER(ASM_OPERAND_REG, ASM_OPERAND_NUM) + ".cfi_endproc\n" + ".size CrashTrampolineAsm, . - CrashTrampolineAsm\n" + ".popsection\n" + ".cfi_startproc\n" + : // No outputs + : FOREACH_REGISTER(ASM_OPERAND_REG, ASM_OPERAND_NUM) #if defined(__aarch64__) - ASM_OPERAND_REG(pc) - ASM_OPERAND_REG(lr) + ASM_OPERAND_REG(pc) ASM_OPERAND_REG(lr) #endif - [StaticCrashHandler] "i" (StaticCrashHandler), - [CFAOffset] "i" (CFAOffset)); + [StaticCrashHandler] "i"(StaticCrashHandler)); } -void CrashHandler(zx_handle_t *Event) { +void CrashHandler() { + assert(SignalHandlerEvent != ZX_HANDLE_INVALID); + // This structure is used to ensure we close handles to objects we create in // this handler. struct ScopedHandle { @@ -251,16 +235,30 @@ void CrashHandler(zx_handle_t *Event) { Self, ZX_EXCEPTION_CHANNEL_DEBUGGER, &Channel.Handle), "_zx_task_create_exception_channel"); - ExitOnErr(_zx_object_signal(*Event, 0, ZX_USER_SIGNAL_0), + ExitOnErr(_zx_object_signal(SignalHandlerEvent, 0, ZX_USER_SIGNAL_0), "_zx_object_signal"); // This thread lives as long as the process in order to keep handling // crashes. In practice, the first crashed thread to reach the end of the // StaticCrashHandler will end the process. while (true) { - ExitOnErr(_zx_object_wait_one(Channel.Handle, ZX_CHANNEL_READABLE, - ZX_TIME_INFINITE, nullptr), - "_zx_object_wait_one"); + zx_wait_item_t WaitItems[] = { + { + .handle = SignalHandlerEvent, + .waitfor = ZX_SIGNAL_HANDLE_CLOSED, + .pending = 0, + }, + { + .handle = Channel.Handle, + .waitfor = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED, + .pending = 0, + }, + }; + auto Status = _zx_object_wait_many( + WaitItems, sizeof(WaitItems) / sizeof(WaitItems[0]), ZX_TIME_INFINITE); + if (Status != ZX_OK || (WaitItems[1].pending & ZX_CHANNEL_READABLE) == 0) { + break; + } zx_exception_info_t ExceptionInfo; ScopedHandle Exception; @@ -296,14 +294,17 @@ void CrashHandler(zx_handle_t *Event) { // onto the stack and jump into a trampoline with CFI instructions on how // to restore it. #if defined(__x86_64__) - uintptr_t StackPtr = GeneralRegisters.rsp - CFAOffset; + uintptr_t StackPtr = + (GeneralRegisters.rsp - (128 + sizeof(GeneralRegisters))) & + -(uintptr_t)16; __unsanitized_memcpy(reinterpret_cast(StackPtr), &GeneralRegisters, sizeof(GeneralRegisters)); GeneralRegisters.rsp = StackPtr; GeneralRegisters.rip = reinterpret_cast(CrashTrampolineAsm); #elif defined(__aarch64__) - uintptr_t StackPtr = GeneralRegisters.sp - CFAOffset; + uintptr_t StackPtr = + (GeneralRegisters.sp - sizeof(GeneralRegisters)) & -(uintptr_t)16; __unsanitized_memcpy(reinterpret_cast(StackPtr), &GeneralRegisters, sizeof(GeneralRegisters)); GeneralRegisters.sp = StackPtr; @@ -327,6 +328,13 @@ void CrashHandler(zx_handle_t *Event) { } } +void StopSignalHandler() { + _zx_handle_close(SignalHandlerEvent); + if (SignalHandler.joinable()) { + SignalHandler.join(); + } +} + } // namespace // Platform specific functions. @@ -356,16 +364,14 @@ void SetSignalHandler(const FuzzingOptions &Options) { return; // Set up the crash handler and wait until it is ready before proceeding. - zx_handle_t Event; - ExitOnErr(_zx_event_create(0, &Event), "_zx_event_create"); + ExitOnErr(_zx_event_create(0, &SignalHandlerEvent), "_zx_event_create"); - std::thread T(CrashHandler, &Event); - zx_status_t Status = - _zx_object_wait_one(Event, ZX_USER_SIGNAL_0, ZX_TIME_INFINITE, nullptr); - _zx_handle_close(Event); + SignalHandler = std::thread(CrashHandler); + zx_status_t Status = _zx_object_wait_one(SignalHandlerEvent, ZX_USER_SIGNAL_0, + ZX_TIME_INFINITE, nullptr); ExitOnErr(Status, "_zx_object_wait_one"); - T.detach(); + std::atexit(StopSignalHandler); } void SleepSeconds(int Seconds) { diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp index 981f9a8b429..717af11bc79 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp @@ -11,7 +11,9 @@ #if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \ LIBFUZZER_EMSCRIPTEN #include "FuzzerCommand.h" +#include "FuzzerInternal.h" +#include #include #include #include @@ -25,6 +27,8 @@ int ExecuteCommand(const Command &Cmd) { int exit_code = system(CmdLine.c_str()); if (WIFEXITED(exit_code)) return WEXITSTATUS(exit_code); + if (WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGINT) + return Fuzzer::InterruptExitCode(); return exit_code; } diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp index 1a54bb569ec..3598758dbb4 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp @@ -204,7 +204,7 @@ const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, } std::string DisassembleCmd(const std::string &FileName) { - Vector command_vector; + std::vector command_vector; command_vector.push_back("dumpbin /summary > nul"); if (ExecuteCommand(Command(command_vector)) == 0) return "dumpbin /disasm " + FileName; diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/tests/CMakeLists.txt b/gnu/llvm/compiler-rt/lib/fuzzer/tests/CMakeLists.txt index 5b3e9064195..10fcfbaa083 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/tests/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/lib/fuzzer/tests/CMakeLists.txt @@ -33,7 +33,8 @@ endif() if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND COMPILER_RT_LIBCXX_PATH AND COMPILER_RT_LIBCXXABI_PATH) - list(APPEND LIBFUZZER_UNITTEST_CFLAGS -nostdinc++) + list(APPEND LIBFUZZER_UNITTEST_CFLAGS -nostdinc++ -fno-exceptions) + list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -nostdlib++ -fno-exceptions) endif() if ("-fvisibility=hidden" IN_LIST LIBFUZZER_CFLAGS) @@ -73,7 +74,7 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST FUZZER_SUPPORTED_ARCH) FuzzerUnitTests "Fuzzer-${arch}-Test" ${arch} SOURCES FuzzerUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} RUNTIME ${LIBFUZZER_TEST_RUNTIME} - DEPS gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} + DEPS llvm_gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) set_target_properties(FuzzerUnitTests PROPERTIES @@ -83,7 +84,7 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST FUZZER_SUPPORTED_ARCH) generate_compiler_rt_tests(FuzzedDataProviderTestObjects FuzzedDataProviderUnitTests "FuzzerUtils-${arch}-Test" ${arch} SOURCES FuzzedDataProviderUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} - DEPS gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} ${COMPILER_RT_SOURCE_DIR}/include/fuzzer/FuzzedDataProvider.h + DEPS llvm_gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} ${COMPILER_RT_SOURCE_DIR}/include/fuzzer/FuzzedDataProvider.h CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) set_target_properties(FuzzedDataProviderUnitTests PROPERTIES diff --git a/gnu/llvm/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp b/gnu/llvm/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp index 974a01ff4ab..5315a8ec016 100644 --- a/gnu/llvm/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp +++ b/gnu/llvm/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp @@ -24,7 +24,8 @@ using namespace fuzzer; // For now, have LLVMFuzzerTestOneInput just to make it link. -// Later we may want to make unittests that actually call LLVMFuzzerTestOneInput. +// Later we may want to make unittests that actually call +// LLVMFuzzerTestOneInput. extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { abort(); } @@ -88,7 +89,7 @@ TEST(Fuzzer, CrossOver) { { 0, 5, 6, 7, 1, 2 } }; for (size_t Len = 1; Len < 8; Len++) { - Set FoundUnits, ExpectedUnitsWitThisLength; + std::set FoundUnits, ExpectedUnitsWitThisLength; for (int Iter = 0; Iter < 3000; Iter++) { C.resize(Len); size_t NewSize = MD->CrossOver(A.data(), A.size(), B.data(), B.size(), @@ -242,7 +243,8 @@ void TestInsertRepeatedBytes(Mutator M, int NumIter) { } TEST(FuzzerMutate, InsertRepeatedBytes1) { - TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes, 10000); + TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes, + 10000); } TEST(FuzzerMutate, InsertRepeatedBytes2) { TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 300000); @@ -557,7 +559,7 @@ TEST(FuzzerDictionary, ParseOneDictionaryEntry) { } TEST(FuzzerDictionary, ParseDictionaryFile) { - Vector Units; + std::vector Units; EXPECT_FALSE(ParseDictionaryFile("zzz\n", &Units)); EXPECT_FALSE(ParseDictionaryFile("", &Units)); EXPECT_TRUE(ParseDictionaryFile("\n", &Units)); @@ -569,11 +571,11 @@ TEST(FuzzerDictionary, ParseDictionaryFile) { EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units)); EXPECT_EQ(Units.size(), 0U); EXPECT_TRUE(ParseDictionaryFile(" #zzzz\naaa=\"aa\"", &Units)); - EXPECT_EQ(Units, Vector({Unit({'a', 'a'})})); + EXPECT_EQ(Units, std::vector({Unit({'a', 'a'})})); EXPECT_TRUE( ParseDictionaryFile(" #zzzz\naaa=\"aa\"\n\nabc=\"abc\"", &Units)); EXPECT_EQ(Units, - Vector({Unit({'a', 'a'}), Unit({'a', 'b', 'c'})})); + std::vector({Unit({'a', 'a'}), Unit({'a', 'b', 'c'})})); } TEST(FuzzerUtil, Base64) { @@ -589,6 +591,42 @@ TEST(FuzzerUtil, Base64) { EXPECT_EQ("YWJjeHl6", Base64({'a', 'b', 'c', 'x', 'y', 'z'})); } +#ifdef __GLIBC__ +class PrintfCapture { + public: + PrintfCapture() { + OldOutputFile = GetOutputFile(); + SetOutputFile(open_memstream(&Buffer, &Size)); + } + ~PrintfCapture() { + fclose(GetOutputFile()); + SetOutputFile(OldOutputFile); + free(Buffer); + } + std::string str() { return std::string(Buffer, Size); } + + private: + char *Buffer; + size_t Size; + FILE *OldOutputFile; +}; + +TEST(FuzzerUtil, PrintASCII) { + auto f = [](const char *Str, const char *PrintAfter = "") { + PrintfCapture Capture; + PrintASCII(reinterpret_cast(Str), strlen(Str), PrintAfter); + return Capture.str(); + }; + EXPECT_EQ("hello", f("hello")); + EXPECT_EQ("c:\\\\", f("c:\\")); + EXPECT_EQ("\\\"hi\\\"", f("\"hi\"")); + EXPECT_EQ("\\011a", f("\ta")); + EXPECT_EQ("\\0111", f("\t1")); + EXPECT_EQ("hello\\012", f("hello\n")); + EXPECT_EQ("hello\n", f("hello", "\n")); +} +#endif + TEST(Corpus, Distribution) { DataFlowTrace DFT; Random Rand(0); @@ -604,7 +642,7 @@ TEST(Corpus, Distribution) { /*FeatureSet*/ {}, DFT, /*BaseII*/ nullptr); - Vector Hist(N); + std::vector Hist(N); for (size_t i = 0; i < N * TriesPerUnit; i++) { Hist[C->ChooseUnitIdxToMutate(Rand)]++; } @@ -614,19 +652,60 @@ TEST(Corpus, Distribution) { } } -template void EQ(const Vector &A, const Vector &B) { +TEST(Corpus, Replace) { + DataFlowTrace DFT; + struct EntropicOptions Entropic = {false, 0xFF, 100, false}; + std::unique_ptr C( + new InputCorpus(/*OutputCorpus*/ "", Entropic)); + InputInfo *FirstII = + C->AddToCorpus(Unit{0x01, 0x00}, /*NumFeatures*/ 1, + /*MayDeleteFile*/ false, /*HasFocusFunction*/ false, + /*ForceAddToCorpus*/ false, + /*TimeOfUnit*/ std::chrono::microseconds(1234), + /*FeatureSet*/ {}, DFT, + /*BaseII*/ nullptr); + InputInfo *SecondII = + C->AddToCorpus(Unit{0x02}, /*NumFeatures*/ 1, + /*MayDeleteFile*/ false, /*HasFocusFunction*/ false, + /*ForceAddToCorpus*/ false, + /*TimeOfUnit*/ std::chrono::microseconds(5678), + /*FeatureSet*/ {}, DFT, + /*BaseII*/ nullptr); + Unit ReplacedU = Unit{0x03}; + + C->Replace(FirstII, ReplacedU, + /*TimeOfUnit*/ std::chrono::microseconds(321)); + + // FirstII should be replaced. + EXPECT_EQ(FirstII->U, Unit{0x03}); + EXPECT_EQ(FirstII->Reduced, true); + EXPECT_EQ(FirstII->TimeOfUnit, std::chrono::microseconds(321)); + std::vector ExpectedSha1(kSHA1NumBytes); + ComputeSHA1(ReplacedU.data(), ReplacedU.size(), ExpectedSha1.data()); + std::vector IISha1(FirstII->Sha1, FirstII->Sha1 + kSHA1NumBytes); + EXPECT_EQ(IISha1, ExpectedSha1); + + // SecondII should not be replaced. + EXPECT_EQ(SecondII->U, Unit{0x02}); + EXPECT_EQ(SecondII->Reduced, false); + EXPECT_EQ(SecondII->TimeOfUnit, std::chrono::microseconds(5678)); +} + +template +void EQ(const std::vector &A, const std::vector &B) { EXPECT_EQ(A, B); } -template void EQ(const Set &A, const Vector &B) { - EXPECT_EQ(A, Set(B.begin(), B.end())); +template void EQ(const std::set &A, const std::vector &B) { + EXPECT_EQ(A, std::set(B.begin(), B.end())); } -void EQ(const Vector &A, const Vector &B) { - Set a; +void EQ(const std::vector &A, + const std::vector &B) { + std::set a; for (const auto &File : A) a.insert(File.Name); - Set b(B.begin(), B.end()); + std::set b(B.begin(), B.end()); EXPECT_EQ(a, b); } @@ -746,9 +825,9 @@ TEST(Merger, Parse) { TEST(Merger, Merge) { Merger M; - Set Features, NewFeatures; - Set Cov, NewCov; - Vector NewFiles; + std::set Features, NewFeatures; + std::set Cov, NewCov; + std::vector NewFiles; // Adds new files and features EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n" @@ -861,6 +940,137 @@ TEST(Merger, Merge) { TRACED_EQ(NewFeatures, {1, 2, 3}); } +TEST(Merger, SetCoverMerge) { + Merger M; + std::set Features, NewFeatures; + std::set Cov, NewCov; + std::vector NewFiles; + + // Adds new files and features + EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6 \n" + "STARTED 2 1002\n" + "FT 2 6 1 3\n" + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 6U); + TRACED_EQ(M.Files, {"A", "B", "C"}); + TRACED_EQ(NewFiles, {"A", "B"}); + TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6}); + + // Doesn't return features or files in the initial corpus. + EXPECT_TRUE(M.Parse("3\n1\nA\nB\nC\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6 \n" + "STARTED 2 1002\n" + "FT 2 6 1 3\n" + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 3U); + TRACED_EQ(M.Files, {"A", "B", "C"}); + TRACED_EQ(NewFiles, {"B"}); + TRACED_EQ(NewFeatures, {4, 5, 6}); + + // No new features, so no new files + EXPECT_TRUE(M.Parse("3\n2\nA\nB\nC\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6 \n" + "STARTED 2 1002\n" + "FT 2 6 1 3\n" + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 0U); + TRACED_EQ(M.Files, {"A", "B", "C"}); + TRACED_EQ(NewFiles, {}); + TRACED_EQ(NewFeatures, {}); + + // Can pass initial features and coverage. + Features = {1, 2, 3}; + Cov = {}; + EXPECT_TRUE(M.Parse("2\n0\nA\nB\n" + "STARTED 0 1000\n" + "FT 0 1 2 3\n" + "STARTED 1 1001\n" + "FT 1 4 5 6\n" + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 3U); + TRACED_EQ(M.Files, {"A", "B"}); + TRACED_EQ(NewFiles, {"B"}); + TRACED_EQ(NewFeatures, {4, 5, 6}); + Features.clear(); + Cov.clear(); + + // Prefer files with a lot of features first (C has 4 features) + // Then prefer B over A due to the smaller size. After choosing C and B, + // A and D have no new features to contribute. + EXPECT_TRUE(M.Parse("4\n0\nA\nB\nC\nD\n" + "STARTED 0 2000\n" + "FT 0 3 5 6\n" + "STARTED 1 1000\n" + "FT 1 4 5 6 \n" + "STARTED 2 1000\n" + "FT 2 1 2 3 4 \n" + "STARTED 3 500\n" + "FT 3 1 \n" + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 6U); + TRACED_EQ(M.Files, {"A", "B", "C", "D"}); + TRACED_EQ(NewFiles, {"C", "B"}); + TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6}); + + // Only 1 file covers all features. + EXPECT_TRUE(M.Parse("4\n1\nA\nB\nC\nD\n" + "STARTED 0 2000\n" + "FT 0 4 5 6 7 8\n" + "STARTED 1 1100\n" + "FT 1 1 2 3 \n" + "STARTED 2 1100\n" + "FT 2 2 3 \n" + "STARTED 3 1000\n" + "FT 3 1 \n" + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 3U); + TRACED_EQ(M.Files, {"A", "B", "C", "D"}); + TRACED_EQ(NewFiles, {"B"}); + TRACED_EQ(NewFeatures, {1, 2, 3}); + + // A Feature has a value greater than (1 << 21) and hence + // there are collisions in the underlying `covered features` + // bitvector. + EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n" + "STARTED 0 2000\n" + "FT 0 1 2 3\n" + "STARTED 1 1000\n" + "FT 1 3 4 5 \n" + "STARTED 2 1000\n" + "FT 2 3 2097153 \n" // Last feature is (2^21 + 1). + "", + true)); + EXPECT_EQ(M.SetCoverMerge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), + 5U); + TRACED_EQ(M.Files, {"A", "B", "C"}); + // File 'C' is not added because it's last feature is considered + // covered due to collision with feature 1. + TRACED_EQ(NewFiles, {"B", "A"}); + TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5}); +} + #undef TRACED_EQ TEST(DFT, BlockCoverage) { @@ -968,7 +1178,7 @@ TEST(Fuzzer, ForEachNonZeroByte) { 0, 0, 0, 0, 0, 0, 0, 8, 9, 9, 9, 9, 9, 9, 9, 9, }; - typedef Vector > Vec; + typedef std::vector> Vec; Vec Res, Expected; auto CB = [&](size_t FirstFeature, size_t Idx, uint8_t V) { Res.push_back({FirstFeature + Idx, V}); @@ -993,7 +1203,7 @@ TEST(Fuzzer, ForEachNonZeroByte) { // FuzzerCommand unit tests. The arguments in the two helper methods below must // match. -static void makeCommandArgs(Vector *ArgsToAdd) { +static void makeCommandArgs(std::vector *ArgsToAdd) { assert(ArgsToAdd); ArgsToAdd->clear(); ArgsToAdd->push_back("foo"); @@ -1029,7 +1239,7 @@ TEST(FuzzerCommand, Create) { EXPECT_EQ(CmdLine, ""); // Explicit constructor - Vector ArgsToAdd; + std::vector ArgsToAdd; makeCommandArgs(&ArgsToAdd); Command InitializedCmd(ArgsToAdd); @@ -1061,7 +1271,7 @@ TEST(FuzzerCommand, Create) { } TEST(FuzzerCommand, ModifyArguments) { - Vector ArgsToAdd; + std::vector ArgsToAdd; makeCommandArgs(&ArgsToAdd); Command Cmd; std::string CmdLine; @@ -1084,7 +1294,7 @@ TEST(FuzzerCommand, ModifyArguments) { } TEST(FuzzerCommand, ModifyFlags) { - Vector ArgsToAdd; + std::vector ArgsToAdd; makeCommandArgs(&ArgsToAdd); Command Cmd(ArgsToAdd); std::string Value, CmdLine; @@ -1116,7 +1326,7 @@ TEST(FuzzerCommand, ModifyFlags) { } TEST(FuzzerCommand, SetOutput) { - Vector ArgsToAdd; + std::vector ArgsToAdd; makeCommandArgs(&ArgsToAdd); Command Cmd(ArgsToAdd); std::string CmdLine; @@ -1196,7 +1406,8 @@ TEST(Entropic, ComputeEnergy) { struct EntropicOptions Entropic = {true, 0xFF, 100, false}; std::unique_ptr C(new InputCorpus("", Entropic)); std::unique_ptr II(new InputInfo()); - Vector> FeatureFreqs = {{1, 3}, {2, 3}, {3, 3}}; + std::vector> FeatureFreqs = { + {1, 3}, {2, 3}, {3, 3}}; II->FeatureFreqs = FeatureFreqs; II->NumExecutedMutations = 0; II->UpdateEnergy(4, false, std::chrono::microseconds(0)); diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/CMakeLists.txt b/gnu/llvm/compiler-rt/lib/gwp_asan/CMakeLists.txt index 638f7034d9f..bb5b2902f99 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/CMakeLists.txt @@ -36,9 +36,10 @@ set(GWP_ASAN_HEADERS set(GWP_ASAN_CFLAGS ${SANITIZER_COMMON_CFLAGS} -fno-rtti -fno-exceptions -nostdinc++ -pthread -fno-omit-frame-pointer) append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC GWP_ASAN_CFLAGS) +# append_list_if(COMPILER_RT_HAS_SANITIZER_COMMON ${SANITIZER_COMMON_CFLAGS} GWP_ASAN_CFLAGS) # Remove -stdlib= which is unused when passing -nostdinc++. -string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) +string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") # Options parsing support is optional. This is an optional library that can be # used by an allocator to automatically parse GwpAsan options from the diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/common.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/common.cpp index b0f6c58bf49..790a331aa66 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/common.cpp +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/common.cpp @@ -105,4 +105,8 @@ size_t AllocatorState::getNearestSlot(uintptr_t Ptr) const { return addrToSlot(this, Ptr + PageSize); // Round up. } +uintptr_t AllocatorState::internallyDetectedErrorFaultAddress() const { + return GuardedPagePoolEnd - 0x10; +} + } // namespace gwp_asan diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/common.h b/gnu/llvm/compiler-rt/lib/gwp_asan/common.h index 7ce367e3ffe..df451021d34 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/common.h +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/common.h @@ -19,7 +19,28 @@ #include namespace gwp_asan { -enum class Error { + +// Magic header that resides in the AllocatorState so that GWP-ASan bugreports +// can be understood by tools at different versions. Out-of-process crash +// handlers, like crashpad on Fuchsia, take the raw contents of the +// AllocationMetatada array and the AllocatorState, and shove them into the +// minidump. Online unpacking of these structs needs to know from which version +// of GWP-ASan it's extracting the information, as the structures are not +// stable. +struct AllocatorVersionMagic { + // The values are copied into the structure at runtime, during + // `GuardedPoolAllocator::init()` so that GWP-ASan remains completely in the + // `.bss` segment. + static constexpr uint8_t kAllocatorVersionMagic[4] = {'A', 'S', 'A', 'N'}; + uint8_t Magic[4] = {}; + // Update the version number when the AllocatorState or AllocationMetadata + // change. + static constexpr uint16_t kAllocatorVersion = 2; + uint16_t Version = 0; + uint16_t Reserved = 0; +}; + +enum class Error : uint8_t { UNKNOWN, USE_AFTER_FREE, DOUBLE_FREE, @@ -77,6 +98,12 @@ struct AllocationMetadata { // Whether this allocation has been deallocated yet. bool IsDeallocated = false; + + // In recoverable mode, whether this allocation has had a crash associated + // with it. This has certain side effects, like meaning this allocation will + // permanently occupy a slot, and won't ever have another crash reported from + // it. + bool HasCrashed = false; }; // This holds the state that's shared between the GWP-ASan allocator and the @@ -84,6 +111,7 @@ struct AllocationMetadata { // set of information required for understanding a GWP-ASan crash. struct AllocatorState { constexpr AllocatorState() {} + AllocatorVersionMagic VersionMagic{}; // Returns whether the provided pointer is a current sampled allocation that // is owned by this pool. @@ -105,6 +133,11 @@ struct AllocatorState { // must be within memory owned by this pool, else the result is undefined. bool isGuardPage(uintptr_t Ptr) const; + // Returns the address that's used by __gwp_asan_get_internal_crash_address() + // and GPA::raiseInternallyDetectedError() to communicate that the SEGV in + // question comes from an internally-detected error. + uintptr_t internallyDetectedErrorFaultAddress() const; + // The number of guarded slots that this pool holds. size_t MaxSimultaneousAllocations = 0; @@ -123,5 +156,38 @@ struct AllocatorState { uintptr_t FailureAddress = 0; }; +// Below are various compile-time checks that the layout of the internal +// GWP-ASan structures are undisturbed. If they are disturbed, the version magic +// number needs to be increased by one, and the asserts need to be updated. +// Out-of-process crash handlers, like breakpad/crashpad, may copy the internal +// GWP-ASan structures into a minidump for offline reconstruction of the crash. +// In order to accomplish this, the offline reconstructor needs to know the +// version of GWP-ASan internal structures that it's unpacking (along with the +// architecture-specific layout info, which is left as an exercise to the crash +// handler). +static_assert(offsetof(AllocatorState, VersionMagic) == 0, ""); +static_assert(sizeof(AllocatorVersionMagic) == 8, ""); +#if defined(__x86_64__) +static_assert(sizeof(AllocatorState) == 56, ""); +static_assert(offsetof(AllocatorState, FailureAddress) == 48, ""); +static_assert(sizeof(AllocationMetadata) == 568, ""); +static_assert(offsetof(AllocationMetadata, IsDeallocated) == 560, ""); +#elif defined(__aarch64__) +static_assert(sizeof(AllocatorState) == 56, ""); +static_assert(offsetof(AllocatorState, FailureAddress) == 48, ""); +static_assert(sizeof(AllocationMetadata) == 568, ""); +static_assert(offsetof(AllocationMetadata, IsDeallocated) == 560, ""); +#elif defined(__i386__) +static_assert(sizeof(AllocatorState) == 32, ""); +static_assert(offsetof(AllocatorState, FailureAddress) == 28, ""); +static_assert(sizeof(AllocationMetadata) == 548, ""); +static_assert(offsetof(AllocationMetadata, IsDeallocated) == 544, ""); +#elif defined(__arm__) +static_assert(sizeof(AllocatorState) == 32, ""); +static_assert(offsetof(AllocatorState, FailureAddress) == 28, ""); +static_assert(sizeof(AllocationMetadata) == 560, ""); +static_assert(offsetof(AllocationMetadata, IsDeallocated) == 552, ""); +#endif // defined($ARCHITECTURE) + } // namespace gwp_asan #endif // GWP_ASAN_COMMON_H_ diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.cpp index 6b4c39edb29..555365c6e6f 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.cpp +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.cpp @@ -31,7 +31,15 @@ bool __gwp_asan_error_is_mine(const gwp_asan::AllocatorState *State, } uintptr_t -__gwp_asan_get_internal_crash_address(const gwp_asan::AllocatorState *State) { +__gwp_asan_get_internal_crash_address(const gwp_asan::AllocatorState *State, + uintptr_t ErrorPtr) { + // There can be a race between internally- and externally-raised faults. The + // fault address from the signal handler is used to discriminate whether it's + // internally- or externally-raised, and the pool maintains a special page at + // the end of the GuardedPagePool specifically for the internally-raised + // faults. + if (ErrorPtr != State->internallyDetectedErrorFaultAddress()) + return 0u; return State->FailureAddress; } @@ -52,7 +60,14 @@ __gwp_asan_diagnose_error(const gwp_asan::AllocatorState *State, if (State->FailureType != Error::UNKNOWN) return State->FailureType; - // Let's try and figure out what the source of this error is. + // Check for use-after-free. + if (addrToMetadata(State, Metadata, ErrorPtr)->IsDeallocated) + return Error::USE_AFTER_FREE; + + // Check for buffer-overflow. Because of allocation alignment or left/right + // page placement, we can have buffer-overflows that don't touch a guarded + // page, but these are not possible to detect unless it's also a + // use-after-free, which is handled above. if (State->isGuardPage(ErrorPtr)) { size_t Slot = State->getNearestSlot(ErrorPtr); const AllocationMetadata *SlotMeta = @@ -67,13 +82,6 @@ __gwp_asan_diagnose_error(const gwp_asan::AllocatorState *State, return Error::BUFFER_UNDERFLOW; } - // Access wasn't a guard page, check for use-after-free. - const AllocationMetadata *SlotMeta = - addrToMetadata(State, Metadata, ErrorPtr); - if (SlotMeta->IsDeallocated) { - return Error::USE_AFTER_FREE; - } - // If we have reached here, the error is still unknown. return Error::UNKNOWN; } diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.h b/gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.h index 4a95069dac5..1ff60edea47 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.h +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.h @@ -46,12 +46,18 @@ __gwp_asan_diagnose_error(const gwp_asan::AllocatorState *State, const gwp_asan::AllocationMetadata *Metadata, uintptr_t ErrorPtr); -// For internally-detected errors (double free, invalid free), this function -// returns the pointer that the error occurred at. If the error is unrelated to -// GWP-ASan, or if the error was caused by a non-internally detected failure, -// this function returns zero. +// This function, provided the fault address from the signal handler, returns +// the following values: +// 1. If the crash was caused by an internally-detected error (invalid free, +// double free), this function returns the pointer that was used for the +// internally-detected bad operation (i.e. the pointer given to free()). +// 2. For externally-detected crashes (use-after-free, buffer-overflow), this +// function returns zero. +// 3. If GWP-ASan wasn't responsible for the crash at all, this function also +// returns zero. uintptr_t -__gwp_asan_get_internal_crash_address(const gwp_asan::AllocatorState *State); +__gwp_asan_get_internal_crash_address(const gwp_asan::AllocatorState *State, + uintptr_t ErrorPtr); // Returns a pointer to the metadata for the allocation that's responsible for // the crash. This metadata should not be dereferenced directly due to API diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp index 8ce5fc9c4df..9017ab7cf7a 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp @@ -8,6 +8,7 @@ #include "gwp_asan/guarded_pool_allocator.h" +#include "gwp_asan/crash_handler.h" #include "gwp_asan/options.h" #include "gwp_asan/utilities.h" @@ -59,6 +60,13 @@ void GuardedPoolAllocator::init(const options::Options &Opts) { SingletonPtr = this; Backtrace = Opts.Backtrace; + State.VersionMagic = {{AllocatorVersionMagic::kAllocatorVersionMagic[0], + AllocatorVersionMagic::kAllocatorVersionMagic[1], + AllocatorVersionMagic::kAllocatorVersionMagic[2], + AllocatorVersionMagic::kAllocatorVersionMagic[3]}, + AllocatorVersionMagic::kAllocatorVersion, + 0}; + State.MaxSimultaneousAllocations = Opts.MaxSimultaneousAllocations; const size_t PageSize = getPlatformPageSize(); @@ -66,8 +74,15 @@ void GuardedPoolAllocator::init(const options::Options &Opts) { assert((PageSize & (PageSize - 1)) == 0); State.PageSize = PageSize; + // Number of pages required = + // + MaxSimultaneousAllocations * maximumAllocationSize (N pages per slot) + // + MaxSimultaneousAllocations (one guard on the left side of each slot) + // + 1 (an extra guard page at the end of the pool, on the right side) + // + 1 (an extra page that's used for reporting internally-detected crashes, + // like double free and invalid free, to the signal handler; see + // raiseInternallyDetectedError() for more info) size_t PoolBytesRequired = - PageSize * (1 + State.MaxSimultaneousAllocations) + + PageSize * (2 + State.MaxSimultaneousAllocations) + State.MaxSimultaneousAllocations * State.maximumAllocationSize(); assert(PoolBytesRequired % PageSize == 0); void *GuardedPoolMemory = reserveGuardedPool(PoolBytesRequired); @@ -251,22 +266,60 @@ void *GuardedPoolAllocator::allocate(size_t Size, size_t Alignment) { return reinterpret_cast(UserPtr); } -void GuardedPoolAllocator::trapOnAddress(uintptr_t Address, Error E) { +void GuardedPoolAllocator::raiseInternallyDetectedError(uintptr_t Address, + Error E) { + // Disable the allocator before setting the internal failure state. In + // non-recoverable mode, the allocator will be permanently disabled, and so + // things will be accessed without locks. + disable(); + + // Races between internally- and externally-raised faults can happen. Right + // now, in this thread we've locked the allocator in order to raise an + // internally-detected fault, and another thread could SIGSEGV to raise an + // externally-detected fault. What will happen is that the other thread will + // wait in the signal handler, as we hold the allocator's locks from the + // disable() above. We'll trigger the signal handler by touching the + // internal-signal-raising address below, and the signal handler from our + // thread will get to run first as we will continue to hold the allocator + // locks until the enable() at the end of this function. Be careful though, if + // this thread receives another SIGSEGV after the disable() above, but before + // touching the internal-signal-raising address below, then this thread will + // get an "externally-raised" SIGSEGV while *also* holding the allocator + // locks, which means this thread's signal handler will deadlock. This could + // be resolved with a re-entrant lock, but asking platforms to implement this + // seems unnecessary given the only way to get a SIGSEGV in this critical + // section is either a memory safety bug in the couple lines of code below (be + // careful!), or someone outside uses `kill(this_thread, SIGSEGV)`, which + // really shouldn't happen. + State.FailureType = E; State.FailureAddress = Address; - // Raise a SEGV by touching first guard page. - volatile char *p = reinterpret_cast(State.GuardedPagePool); + // Raise a SEGV by touching a specific address that identifies to the crash + // handler that this is an internally-raised fault. Changing this address? + // Don't forget to update __gwp_asan_get_internal_crash_address. + volatile char *p = + reinterpret_cast(State.internallyDetectedErrorFaultAddress()); *p = 0; - // Normally, would be __builtin_unreachable(), but because of - // https://bugs.llvm.org/show_bug.cgi?id=47480, unreachable will DCE the - // volatile store above, even though it has side effects. - __builtin_trap(); -} -void GuardedPoolAllocator::stop() { - getThreadLocals()->RecursiveGuard = true; - PoolMutex.tryLock(); + // This should never be reached in non-recoverable mode. Ensure that the + // signal handler called handleRecoverablePostCrashReport(), which was + // responsible for re-setting these fields. + assert(State.FailureType == Error::UNKNOWN); + assert(State.FailureAddress == 0u); + + // In recoverable mode, the signal handler (after dumping the crash) marked + // the page containing the InternalFaultSegvAddress as read/writeable, to + // allow the second touch to succeed after returning from the signal handler. + // Now, we need to mark the page as non-read/write-able again, so future + // internal faults can be raised. + deallocateInGuardedPool( + reinterpret_cast(getPageAddr( + State.internallyDetectedErrorFaultAddress(), State.PageSize)), + State.PageSize); + + // And now we're done with patching ourselves back up, enable the allocator. + enable(); } void GuardedPoolAllocator::deallocate(void *Ptr) { @@ -275,19 +328,25 @@ void GuardedPoolAllocator::deallocate(void *Ptr) { size_t Slot = State.getNearestSlot(UPtr); uintptr_t SlotStart = State.slotToAddr(Slot); AllocationMetadata *Meta = addrToMetadata(UPtr); + + // If this allocation is responsible for crash, never recycle it. Turn the + // deallocate() call into a no-op. + if (Meta->HasCrashed) + return; + if (Meta->Addr != UPtr) { - // If multiple errors occur at the same time, use the first one. - ScopedLock L(PoolMutex); - trapOnAddress(UPtr, Error::INVALID_FREE); + raiseInternallyDetectedError(UPtr, Error::INVALID_FREE); + return; + } + if (Meta->IsDeallocated) { + raiseInternallyDetectedError(UPtr, Error::DOUBLE_FREE); + return; } // Intentionally scope the mutex here, so that other threads can access the // pool during the expensive markInaccessible() call. { ScopedLock L(PoolMutex); - if (Meta->IsDeallocated) { - trapOnAddress(UPtr, Error::DOUBLE_FREE); - } // Ensure that the deallocation is recorded before marking the page as // inaccessible. Otherwise, a racy use-after-free will have inconsistent @@ -311,6 +370,62 @@ void GuardedPoolAllocator::deallocate(void *Ptr) { freeSlot(Slot); } +// Thread-compatible, protected by PoolMutex. +static bool PreviousRecursiveGuard; + +void GuardedPoolAllocator::preCrashReport(void *Ptr) { + assert(pointerIsMine(Ptr) && "Pointer is not mine!"); + uintptr_t InternalCrashAddr = __gwp_asan_get_internal_crash_address( + &State, reinterpret_cast(Ptr)); + if (!InternalCrashAddr) + disable(); + + // If something in the signal handler calls malloc() while dumping the + // GWP-ASan report (e.g. backtrace_symbols()), make sure that GWP-ASan doesn't + // service that allocation. `PreviousRecursiveGuard` is protected by the + // allocator locks taken in disable(), either explicitly above for + // externally-raised errors, or implicitly in raiseInternallyDetectedError() + // for internally-detected errors. + PreviousRecursiveGuard = getThreadLocals()->RecursiveGuard; + getThreadLocals()->RecursiveGuard = true; +} + +void GuardedPoolAllocator::postCrashReportRecoverableOnly(void *SignalPtr) { + uintptr_t SignalUPtr = reinterpret_cast(SignalPtr); + uintptr_t InternalCrashAddr = + __gwp_asan_get_internal_crash_address(&State, SignalUPtr); + uintptr_t ErrorUptr = InternalCrashAddr ?: SignalUPtr; + + AllocationMetadata *Metadata = addrToMetadata(ErrorUptr); + Metadata->HasCrashed = true; + + allocateInGuardedPool( + reinterpret_cast(getPageAddr(SignalUPtr, State.PageSize)), + State.PageSize); + + // Clear the internal state in order to not confuse the crash handler if a + // use-after-free or buffer-overflow comes from a different allocation in the + // future. + if (InternalCrashAddr) { + State.FailureType = Error::UNKNOWN; + State.FailureAddress = 0; + } + + size_t Slot = State.getNearestSlot(ErrorUptr); + // If the slot is available, remove it permanently. + for (size_t i = 0; i < FreeSlotsLength; ++i) { + if (FreeSlots[i] == Slot) { + FreeSlots[i] = FreeSlots[FreeSlotsLength - 1]; + FreeSlotsLength -= 1; + break; + } + } + + getThreadLocals()->RecursiveGuard = PreviousRecursiveGuard; + if (!InternalCrashAddr) + enable(); +} + size_t GuardedPoolAllocator::getSize(const void *Ptr) { assert(pointerIsMine(Ptr)); ScopedLock L(PoolMutex); diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h b/gnu/llvm/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h index 6d2ce2576c1..de07b6798c1 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h @@ -67,11 +67,6 @@ public: // allocate. void iterate(void *Base, size_t Size, iterate_callback Cb, void *Arg); - // This function is used to signal the allocator to indefinitely stop - // functioning, as a crash has occurred. This stops the allocator from - // servicing any further allocations permanently. - void stop(); - // Return whether the allocation should be randomly chosen for sampling. GWP_ASAN_ALWAYS_INLINE bool shouldSample() { // NextSampleCounter == 0 means we "should regenerate the counter". @@ -115,6 +110,12 @@ public: // Returns a pointer to the AllocatorState region. const AllocatorState *getAllocatorState() const { return &State; } + // Functions that the signal handler is responsible for calling, while + // providing the SEGV pointer, prior to dumping the crash, and after dumping + // the crash (in recoverable mode only). + void preCrashReport(void *Ptr); + void postCrashReportRecoverableOnly(void *Ptr); + // Exposed as protected for testing. protected: // Returns the actual allocation size required to service an allocation with @@ -185,7 +186,7 @@ private: // Raise a SEGV and set the corresponding fields in the Allocator's State in // order to tell the crash handler what happened. Used when errors are // detected internally (Double Free, Invalid Free). - void trapOnAddress(uintptr_t Address, Error E); + void raiseInternallyDetectedError(uintptr_t Address, Error E); static GuardedPoolAllocator *getSingleton(); diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp index e6cce86e3b7..f8b9cbdb793 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp @@ -72,7 +72,9 @@ static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength, return; } - StackTrace.Print(); + __sanitizer::InternalScopedString buffer; + StackTrace.PrintTo(&buffer); + Printf("%s\n", buffer.data()); } } // anonymous namespace diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/optional/segv_handler.h b/gnu/llvm/compiler-rt/lib/gwp_asan/optional/segv_handler.h index 87d9fe1dff1..72105ded7d5 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/optional/segv_handler.h +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/optional/segv_handler.h @@ -23,7 +23,8 @@ namespace segv_handler { // before this function. void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf, gwp_asan::backtrace::PrintBacktrace_t PrintBacktrace, - gwp_asan::backtrace::SegvBacktrace_t SegvBacktrace); + gwp_asan::backtrace::SegvBacktrace_t SegvBacktrace, + bool Recoverable = false); // Uninistall the signal handlers, test-only. void uninstallSignalHandlers(); diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/optional/segv_handler_fuchsia.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/optional/segv_handler_fuchsia.cpp index 966d7d0bd99..f5ff35e27ac 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/optional/segv_handler_fuchsia.cpp +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/optional/segv_handler_fuchsia.cpp @@ -15,7 +15,8 @@ namespace segv_handler { void installSignalHandlers(gwp_asan::GuardedPoolAllocator * /* GPA */, Printf_t /* Printf */, backtrace::PrintBacktrace_t /* PrintBacktrace */, - backtrace::SegvBacktrace_t /* SegvBacktrace */) {} + backtrace::SegvBacktrace_t /* SegvBacktrace */, + bool /* Recoverable */) {} void uninstallSignalHandlers() {} } // namespace segv_handler diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp index 5c9bb9f3a2e..e012963bffd 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp @@ -47,15 +47,12 @@ void printHeader(Error E, uintptr_t AccessPtr, // appended to a log file automatically per Printf() call. constexpr size_t kDescriptionBufferLen = 128; char DescriptionBuffer[kDescriptionBufferLen] = ""; + + bool AccessWasInBounds = false; if (E != Error::UNKNOWN && Metadata != nullptr) { uintptr_t Address = __gwp_asan_get_allocation_address(Metadata); size_t Size = __gwp_asan_get_allocation_size(Metadata); - if (E == Error::USE_AFTER_FREE) { - snprintf(DescriptionBuffer, kDescriptionBufferLen, - "(%zu byte%s into a %zu-byte allocation at 0x%zx) ", - AccessPtr - Address, (AccessPtr - Address == 1) ? "" : "s", Size, - Address); - } else if (AccessPtr < Address) { + if (AccessPtr < Address) { snprintf(DescriptionBuffer, kDescriptionBufferLen, "(%zu byte%s to the left of a %zu-byte allocation at 0x%zx) ", Address - AccessPtr, (Address - AccessPtr == 1) ? "" : "s", Size, @@ -65,9 +62,15 @@ void printHeader(Error E, uintptr_t AccessPtr, "(%zu byte%s to the right of a %zu-byte allocation at 0x%zx) ", AccessPtr - Address, (AccessPtr - Address == 1) ? "" : "s", Size, Address); - } else { + } else if (E == Error::DOUBLE_FREE) { snprintf(DescriptionBuffer, kDescriptionBufferLen, "(a %zu-byte allocation) ", Size); + } else { + AccessWasInBounds = true; + snprintf(DescriptionBuffer, kDescriptionBufferLen, + "(%zu byte%s into a %zu-byte allocation at 0x%zx) ", + AccessPtr - Address, (AccessPtr - Address == 1) ? "" : "s", Size, + Address); } } @@ -81,8 +84,19 @@ void printHeader(Error E, uintptr_t AccessPtr, else snprintf(ThreadBuffer, kThreadBufferLen, "%" PRIu64, ThreadID); - Printf("%s at 0x%zx %sby thread %s here:\n", gwp_asan::ErrorToString(E), - AccessPtr, DescriptionBuffer, ThreadBuffer); + const char *OutOfBoundsAndUseAfterFreeWarning = ""; + if (E == Error::USE_AFTER_FREE && !AccessWasInBounds) { + OutOfBoundsAndUseAfterFreeWarning = + " (warning: buffer overflow/underflow detected on a free()'d " + "allocation. This either means you have a buffer-overflow and a " + "use-after-free at the same time, or you have a long-lived " + "use-after-free bug where the allocation/deallocation metadata below " + "has already been overwritten and is likely bogus)"; + } + + Printf("%s%s at 0x%zx %sby thread %s here:\n", gwp_asan::ErrorToString(E), + OutOfBoundsAndUseAfterFreeWarning, AccessPtr, DescriptionBuffer, + ThreadBuffer); } void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State, @@ -92,19 +106,31 @@ void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State, assert(State && "dumpReport missing Allocator State."); assert(Metadata && "dumpReport missing Metadata."); assert(Printf && "dumpReport missing Printf."); + assert(__gwp_asan_error_is_mine(State, ErrorPtr) && + "dumpReport() called on a non-GWP-ASan error."); - if (!__gwp_asan_error_is_mine(State, ErrorPtr)) + uintptr_t InternalErrorPtr = + __gwp_asan_get_internal_crash_address(State, ErrorPtr); + if (InternalErrorPtr) + ErrorPtr = InternalErrorPtr; + + const gwp_asan::AllocationMetadata *AllocMeta = + __gwp_asan_get_metadata(State, Metadata, ErrorPtr); + + // It's unusual for a signal handler to be invoked multiple times for the same + // allocation, but it's possible in various scenarios, like: + // 1. A double-free or invalid-free was invoked in one thread at the same + // time as a buffer-overflow or use-after-free in another thread, or + // 2. Two threads do a use-after-free or buffer-overflow at the same time. + // In these instances, we've already dumped a report for this allocation, so + // skip dumping this issue as well. + if (AllocMeta->HasCrashed) return; Printf("*** GWP-ASan detected a memory error ***\n"); ScopedEndOfReportDecorator Decorator(Printf); - uintptr_t InternalErrorPtr = __gwp_asan_get_internal_crash_address(State); - if (InternalErrorPtr != 0u) - ErrorPtr = InternalErrorPtr; - Error E = __gwp_asan_diagnose_error(State, Metadata, ErrorPtr); - if (E == Error::UNKNOWN) { Printf("GWP-ASan cannot provide any more information about this error. " "This may occur due to a wild memory access into the GWP-ASan pool, " @@ -112,9 +138,6 @@ void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State, return; } - const gwp_asan::AllocationMetadata *AllocMeta = - __gwp_asan_get_metadata(State, Metadata, ErrorPtr); - // Print the error header. printHeader(E, ErrorPtr, AllocMeta, Printf); @@ -154,23 +177,33 @@ void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State, struct sigaction PreviousHandler; bool SignalHandlerInstalled; +bool RecoverableSignal; gwp_asan::GuardedPoolAllocator *GPAForSignalHandler; Printf_t PrintfForSignalHandler; PrintBacktrace_t PrintBacktraceForSignalHandler; SegvBacktrace_t BacktraceForSignalHandler; static void sigSegvHandler(int sig, siginfo_t *info, void *ucontext) { - if (GPAForSignalHandler) { - GPAForSignalHandler->stop(); + const gwp_asan::AllocatorState *State = + GPAForSignalHandler->getAllocatorState(); + void *FaultAddr = info->si_addr; + uintptr_t FaultAddrUPtr = reinterpret_cast(FaultAddr); - dumpReport(reinterpret_cast(info->si_addr), - GPAForSignalHandler->getAllocatorState(), - GPAForSignalHandler->getMetadataRegion(), + if (__gwp_asan_error_is_mine(State, FaultAddrUPtr)) { + GPAForSignalHandler->preCrashReport(FaultAddr); + + dumpReport(FaultAddrUPtr, State, GPAForSignalHandler->getMetadataRegion(), BacktraceForSignalHandler, PrintfForSignalHandler, PrintBacktraceForSignalHandler, ucontext); + + if (RecoverableSignal) { + GPAForSignalHandler->postCrashReportRecoverableOnly(FaultAddr); + return; + } } - // Process any previous handlers. + // Process any previous handlers as long as the crash wasn't a GWP-ASan crash + // in recoverable mode. if (PreviousHandler.sa_flags & SA_SIGINFO) { PreviousHandler.sa_sigaction(sig, info, ucontext); } else if (PreviousHandler.sa_handler == SIG_DFL) { @@ -196,7 +229,7 @@ namespace segv_handler { void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf, PrintBacktrace_t PrintBacktrace, - SegvBacktrace_t SegvBacktrace) { + SegvBacktrace_t SegvBacktrace, bool Recoverable) { assert(GPA && "GPA wasn't provided to installSignalHandlers."); assert(Printf && "Printf wasn't provided to installSignalHandlers."); assert(PrintBacktrace && @@ -207,6 +240,7 @@ void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf, PrintfForSignalHandler = Printf; PrintBacktraceForSignalHandler = PrintBacktrace; BacktraceForSignalHandler = SegvBacktrace; + RecoverableSignal = Recoverable; struct sigaction Action = {}; Action.sa_sigaction = sigSegvHandler; diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/options.inc b/gnu/llvm/compiler-rt/lib/gwp_asan/options.inc index 9900a2ac40d..3a593216e8d 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/options.inc +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/options.inc @@ -49,6 +49,16 @@ GWP_ASAN_OPTION( "the same. Note, if the previously installed SIGSEGV handler is SIG_IGN, " "we terminate the process after dumping the error report.") +GWP_ASAN_OPTION( + bool, Recoverable, false, + "Install GWP-ASan's signal handler in recoverable mode. This means that " + "upon GWP-ASan detecting an error, it'll print the error report, but *not* " + "crash. Only one crash per sampled allocation will ever be recorded, and " + "if a sampled allocation does actually cause a crash, it'll permanently " + "occupy a slot in the pool. The recoverable mode also means that " + "previously-installed signal handlers will only be triggered for " + "non-GWP-ASan errors, as all GWP-ASan errors won't be forwarded.") + GWP_ASAN_OPTION(bool, InstallForkHandlers, true, "Install GWP-ASan atfork handlers to acquire internal locks " "before fork and release them after.") diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp index adb7330a431..c036ebe3efc 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp @@ -98,6 +98,10 @@ size_t GuardedPoolAllocator::getPlatformPageSize() { } void GuardedPoolAllocator::installAtFork() { + static bool AtForkInstalled = false; + if (AtForkInstalled) + return; + AtForkInstalled = true; auto Disable = []() { if (auto *S = getSingleton()) S->disable(); diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/scripts/symbolize.sh b/gnu/llvm/compiler-rt/lib/gwp_asan/scripts/symbolize.sh index 6974ee81670..0027fa00f0f 100755 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/scripts/symbolize.sh +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/scripts/symbolize.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # The lines that we're looking to symbolize look like this: #0 ./a.out(_foo+0x3e6) [0x55a52e64c696] diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt index abc02a49637..046ca7ce679 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt @@ -3,6 +3,8 @@ include(CompilerRTCompile) set(GWP_ASAN_UNITTEST_CFLAGS ${COMPILER_RT_UNITTEST_CFLAGS} ${COMPILER_RT_GTEST_CFLAGS} + ${SANITIZER_TEST_CXX_CFLAGS} + -std=c++17 -I${COMPILER_RT_SOURCE_DIR}/lib/ -O2 -g @@ -24,7 +26,8 @@ set(GWP_ASAN_UNITTESTS harness.cpp enable_disable.cpp late_init.cpp - options.cpp) + options.cpp + recoverable.cpp) set(GWP_ASAN_UNIT_TEST_HEADERS ${GWP_ASAN_HEADERS} @@ -33,7 +36,10 @@ set(GWP_ASAN_UNIT_TEST_HEADERS add_custom_target(GwpAsanUnitTests) set_target_properties(GwpAsanUnitTests PROPERTIES FOLDER "Compiler-RT Tests") -set(GWP_ASAN_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_LINK_FLAGS} -ldl) +set(GWP_ASAN_UNITTEST_LINK_FLAGS + ${COMPILER_RT_UNITTEST_LINK_FLAGS} -ldl + ${COMPILER_RT_UNWINDER_LINK_LIBS} + ${SANITIZER_TEST_CXX_LIBRARIES}) list(APPEND GWP_ASAN_UNITTEST_LINK_FLAGS --driver-mode=g++) if(NOT WIN32) list(APPEND GWP_ASAN_UNITTEST_LINK_FLAGS -pthread) @@ -66,7 +72,7 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST GWP_ASAN_SUPPORTED_ARCH) GwpAsanUnitTests "GwpAsan-${arch}-Test" ${arch} SOURCES ${GWP_ASAN_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE} RUNTIME ${GWP_ASAN_TEST_RUNTIME} - DEPS gtest ${GWP_ASAN_UNIT_TEST_HEADERS} + DEPS llvm_gtest ${GWP_ASAN_UNIT_TEST_HEADERS} CFLAGS ${GWP_ASAN_UNITTEST_CFLAGS} LINK_FLAGS ${GWP_ASAN_UNITTEST_LINK_FLAGS}) set_target_properties(GwpAsanUnitTests PROPERTIES diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/alignment.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/alignment.cpp index 5f24a9a1bd8..9f150467c79 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/alignment.cpp +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/alignment.cpp @@ -34,81 +34,81 @@ public: // numerics of the testing. TEST(AlignmentTest, LeftAlignedAllocs) { // Alignment < Page Size. - EXPECT_EQ(0x4000, AlignmentTestGPA::alignUp( - /* Ptr */ 0x4000, /* Alignment */ 0x1)); + EXPECT_EQ(0x4000u, AlignmentTestGPA::alignUp( + /* Ptr */ 0x4000, /* Alignment */ 0x1)); // Alignment == Page Size. - EXPECT_EQ(0x4000, AlignmentTestGPA::alignUp( - /* Ptr */ 0x4000, /* Alignment */ 0x1000)); + EXPECT_EQ(0x4000u, AlignmentTestGPA::alignUp( + /* Ptr */ 0x4000, /* Alignment */ 0x1000)); // Alignment > Page Size. - EXPECT_EQ(0x4000, AlignmentTestGPA::alignUp( - /* Ptr */ 0x4000, /* Alignment */ 0x4000)); + EXPECT_EQ(0x4000u, AlignmentTestGPA::alignUp( + /* Ptr */ 0x4000, /* Alignment */ 0x4000)); } TEST(AlignmentTest, SingleByteAllocs) { // Alignment < Page Size. - EXPECT_EQ(0x1, + EXPECT_EQ(0x1u, AlignmentTestGPA::getRequiredBackingSize( /* Size */ 0x1, /* Alignment */ 0x1, /* PageSize */ 0x1000)); - EXPECT_EQ(0x7fff, AlignmentTestGPA::alignDown( - /* Ptr */ 0x8000 - 0x1, /* Alignment */ 0x1)); + EXPECT_EQ(0x7fffu, AlignmentTestGPA::alignDown( + /* Ptr */ 0x8000 - 0x1, /* Alignment */ 0x1)); // Alignment == Page Size. - EXPECT_EQ(0x1, + EXPECT_EQ(0x1u, AlignmentTestGPA::getRequiredBackingSize( /* Size */ 0x1, /* Alignment */ 0x1000, /* PageSize */ 0x1000)); - EXPECT_EQ(0x7000, AlignmentTestGPA::alignDown( - /* Ptr */ 0x8000 - 0x1, /* Alignment */ 0x1000)); + EXPECT_EQ(0x7000u, AlignmentTestGPA::alignDown( + /* Ptr */ 0x8000 - 0x1, /* Alignment */ 0x1000)); // Alignment > Page Size. - EXPECT_EQ(0x3001, + EXPECT_EQ(0x3001u, AlignmentTestGPA::getRequiredBackingSize( /* Size */ 0x1, /* Alignment */ 0x4000, /* PageSize */ 0x1000)); - EXPECT_EQ(0x4000, AlignmentTestGPA::alignDown( - /* Ptr */ 0x8000 - 0x1, /* Alignment */ 0x4000)); + EXPECT_EQ(0x4000u, AlignmentTestGPA::alignDown( + /* Ptr */ 0x8000 - 0x1, /* Alignment */ 0x4000)); } TEST(AlignmentTest, PageSizedAllocs) { // Alignment < Page Size. - EXPECT_EQ(0x1000, + EXPECT_EQ(0x1000u, AlignmentTestGPA::getRequiredBackingSize( /* Size */ 0x1000, /* Alignment */ 0x1, /* PageSize */ 0x1000)); - EXPECT_EQ(0x7000, AlignmentTestGPA::alignDown( - /* Ptr */ 0x8000 - 0x1000, /* Alignment */ 0x1)); + EXPECT_EQ(0x7000u, AlignmentTestGPA::alignDown( + /* Ptr */ 0x8000 - 0x1000, /* Alignment */ 0x1)); // Alignment == Page Size. - EXPECT_EQ(0x1000, AlignmentTestGPA::getRequiredBackingSize( - /* Size */ 0x1000, /* Alignment */ 0x1000, - /* PageSize */ 0x1000)); - EXPECT_EQ(0x7000, AlignmentTestGPA::alignDown( - /* Ptr */ 0x8000 - 0x1000, /* Alignment */ 0x1000)); + EXPECT_EQ(0x1000u, AlignmentTestGPA::getRequiredBackingSize( + /* Size */ 0x1000, /* Alignment */ 0x1000, + /* PageSize */ 0x1000)); + EXPECT_EQ(0x7000u, AlignmentTestGPA::alignDown( + /* Ptr */ 0x8000 - 0x1000, /* Alignment */ 0x1000)); // Alignment > Page Size. - EXPECT_EQ(0x4000, AlignmentTestGPA::getRequiredBackingSize( - /* Size */ 0x1000, /* Alignment */ 0x4000, - /* PageSize */ 0x1000)); - EXPECT_EQ(0x4000, AlignmentTestGPA::alignDown( - /* Ptr */ 0x8000 - 0x1000, /* Alignment */ 0x4000)); + EXPECT_EQ(0x4000u, AlignmentTestGPA::getRequiredBackingSize( + /* Size */ 0x1000, /* Alignment */ 0x4000, + /* PageSize */ 0x1000)); + EXPECT_EQ(0x4000u, AlignmentTestGPA::alignDown( + /* Ptr */ 0x8000 - 0x1000, /* Alignment */ 0x4000)); } TEST(AlignmentTest, MoreThanPageAllocs) { // Alignment < Page Size. - EXPECT_EQ(0x2fff, + EXPECT_EQ(0x2fffu, AlignmentTestGPA::getRequiredBackingSize( /* Size */ 0x2fff, /* Alignment */ 0x1, /* PageSize */ 0x1000)); - EXPECT_EQ(0x5001, AlignmentTestGPA::alignDown( - /* Ptr */ 0x8000 - 0x2fff, /* Alignment */ 0x1)); + EXPECT_EQ(0x5001u, AlignmentTestGPA::alignDown( + /* Ptr */ 0x8000 - 0x2fff, /* Alignment */ 0x1)); // Alignment == Page Size. - EXPECT_EQ(0x2fff, AlignmentTestGPA::getRequiredBackingSize( - /* Size */ 0x2fff, /* Alignment */ 0x1000, - /* PageSize */ 0x1000)); - EXPECT_EQ(0x5000, AlignmentTestGPA::alignDown( - /* Ptr */ 0x8000 - 0x2fff, /* Alignment */ 0x1000)); + EXPECT_EQ(0x2fffu, AlignmentTestGPA::getRequiredBackingSize( + /* Size */ 0x2fff, /* Alignment */ 0x1000, + /* PageSize */ 0x1000)); + EXPECT_EQ(0x5000u, AlignmentTestGPA::alignDown( + /* Ptr */ 0x8000 - 0x2fff, /* Alignment */ 0x1000)); // Alignment > Page Size. - EXPECT_EQ(0x5fff, AlignmentTestGPA::getRequiredBackingSize( - /* Size */ 0x2fff, /* Alignment */ 0x4000, - /* PageSize */ 0x1000)); - EXPECT_EQ(0x4000, AlignmentTestGPA::alignDown( - /* Ptr */ 0x8000 - 0x2fff, /* Alignment */ 0x4000)); + EXPECT_EQ(0x5fffu, AlignmentTestGPA::getRequiredBackingSize( + /* Size */ 0x2fff, /* Alignment */ 0x4000, + /* PageSize */ 0x1000)); + EXPECT_EQ(0x4000u, AlignmentTestGPA::alignDown( + /* Ptr */ 0x8000 - 0x2fff, /* Alignment */ 0x4000)); } diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/backtrace.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/backtrace.cpp index a4eb8eb9b21..e8789943962 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/backtrace.cpp +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/backtrace.cpp @@ -6,46 +6,38 @@ // //===----------------------------------------------------------------------===// +#include #include #include "gwp_asan/common.h" #include "gwp_asan/crash_handler.h" #include "gwp_asan/tests/harness.h" -// Optnone to ensure that the calls to these functions are not optimized away, -// as we're looking for them in the backtraces. -__attribute((optnone)) void * -AllocateMemory(gwp_asan::GuardedPoolAllocator &GPA) { - return GPA.allocate(1); -} -__attribute((optnone)) void -DeallocateMemory(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr) { - GPA.deallocate(Ptr); -} -__attribute((optnone)) void -DeallocateMemory2(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr) { - GPA.deallocate(Ptr); -} -__attribute__((optnone)) void TouchMemory(void *Ptr) { - *(reinterpret_cast(Ptr)) = 7; -} - -TEST_F(BacktraceGuardedPoolAllocatorDeathTest, DoubleFree) { +TEST_P(BacktraceGuardedPoolAllocatorDeathTest, DoubleFree) { void *Ptr = AllocateMemory(GPA); DeallocateMemory(GPA, Ptr); - std::string DeathRegex = "Double Free.*"; - DeathRegex.append("DeallocateMemory2.*"); - - DeathRegex.append("was deallocated.*"); - DeathRegex.append("DeallocateMemory.*"); - - DeathRegex.append("was allocated.*"); - DeathRegex.append("AllocateMemory.*"); - ASSERT_DEATH(DeallocateMemory2(GPA, Ptr), DeathRegex); + std::string DeathRegex = "Double Free.*DeallocateMemory2.*"; + DeathRegex.append("was deallocated.*DeallocateMemory[^2].*"); + DeathRegex.append("was allocated.*AllocateMemory"); + if (!Recoverable) { + ASSERT_DEATH(DeallocateMemory2(GPA, Ptr), DeathRegex); + return; + } + + // For recoverable, assert that DeallocateMemory2() doesn't crash. + DeallocateMemory2(GPA, Ptr); + // Fuchsia's zxtest doesn't have an EXPECT_THAT(testing::MatchesRegex(), ...), + // so check the regex manually. + EXPECT_TRUE(std::regex_search( + GetOutputBuffer(), + std::basic_regex(DeathRegex, std::regex_constants::extended))) + << "Regex \"" << DeathRegex + << "\" was not found in input:\n============\n" + << GetOutputBuffer() << "\n============"; } -TEST_F(BacktraceGuardedPoolAllocatorDeathTest, UseAfterFree) { +TEST_P(BacktraceGuardedPoolAllocatorDeathTest, UseAfterFree) { #if defined(__linux__) && __ARM_ARCH == 7 // Incomplete backtrace on Armv7 Linux GTEST_SKIP(); @@ -54,17 +46,32 @@ TEST_F(BacktraceGuardedPoolAllocatorDeathTest, UseAfterFree) { void *Ptr = AllocateMemory(GPA); DeallocateMemory(GPA, Ptr); - std::string DeathRegex = "Use After Free.*"; - DeathRegex.append("TouchMemory.*"); - - DeathRegex.append("was deallocated.*"); - DeathRegex.append("DeallocateMemory.*"); - - DeathRegex.append("was allocated.*"); - DeathRegex.append("AllocateMemory.*"); - ASSERT_DEATH(TouchMemory(Ptr), DeathRegex); + std::string DeathRegex = "Use After Free.*TouchMemory.*"; + DeathRegex.append("was deallocated.*DeallocateMemory[^2].*"); + DeathRegex.append("was allocated.*AllocateMemory"); + + if (!Recoverable) { + ASSERT_DEATH(TouchMemory(Ptr), DeathRegex); + return; + } + + // For recoverable, assert that TouchMemory() doesn't crash. + TouchMemory(Ptr); + // Fuchsia's zxtest doesn't have an EXPECT_THAT(testing::MatchesRegex(), ...), + // so check the regex manually. + EXPECT_TRUE(std::regex_search( + GetOutputBuffer(), + std::basic_regex(DeathRegex, std::regex_constants::extended))) + << "Regex \"" << DeathRegex + << "\" was not found in input:\n============\n" + << GetOutputBuffer() << "\n============"; + ; } +INSTANTIATE_TEST_SUITE_P(RecoverableSignalDeathTest, + BacktraceGuardedPoolAllocatorDeathTest, + /* Recoverable */ testing::Bool()); + TEST(Backtrace, Short) { gwp_asan::AllocationMetadata Meta; Meta.AllocationTrace.RecordBacktrace( diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/crash_handler_api.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/crash_handler_api.cpp index 4cdb5694842..598b7b87892 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/crash_handler_api.cpp +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/crash_handler_api.cpp @@ -40,7 +40,8 @@ protected: void setupState() { State.GuardedPagePool = 0x2000; - State.GuardedPagePoolEnd = 0xb000; + State.GuardedPagePoolEnd = 0xc000; + InternalFaultAddr = State.GuardedPagePoolEnd - 0x10; State.MaxSimultaneousAllocations = 4; // 0x3000, 0x5000, 0x7000, 0x9000. State.PageSize = 0x1000; } @@ -100,6 +101,7 @@ protected: static uintptr_t BacktraceConstants[kNumBacktraceConstants]; AllocatorState State = {}; AllocationMetadata Metadata[4] = {}; + uintptr_t InternalFaultAddr; }; uintptr_t CrashHandlerAPITest::BacktraceConstants[kNumBacktraceConstants] = { @@ -125,7 +127,7 @@ TEST_F(CrashHandlerAPITest, PointerNotAllocated) { EXPECT_TRUE(__gwp_asan_error_is_mine(&State, FailureAddress)); EXPECT_EQ(Error::UNKNOWN, __gwp_asan_diagnose_error(&State, Metadata, FailureAddress)); - EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State)); + EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State, FailureAddress)); EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State, Metadata, FailureAddress)); } @@ -140,7 +142,8 @@ TEST_F(CrashHandlerAPITest, DoubleFree) { EXPECT_TRUE(__gwp_asan_error_is_mine(&State)); EXPECT_EQ(Error::DOUBLE_FREE, __gwp_asan_diagnose_error(&State, Metadata, 0x0)); - EXPECT_EQ(FailureAddress, __gwp_asan_get_internal_crash_address(&State)); + EXPECT_EQ(FailureAddress, + __gwp_asan_get_internal_crash_address(&State, InternalFaultAddr)); checkMetadata(Index, FailureAddress); } @@ -155,7 +158,8 @@ TEST_F(CrashHandlerAPITest, InvalidFree) { EXPECT_TRUE(__gwp_asan_error_is_mine(&State)); EXPECT_EQ(Error::INVALID_FREE, __gwp_asan_diagnose_error(&State, Metadata, 0x0)); - EXPECT_EQ(FailureAddress, __gwp_asan_get_internal_crash_address(&State)); + EXPECT_EQ(FailureAddress, + __gwp_asan_get_internal_crash_address(&State, InternalFaultAddr)); checkMetadata(Index, FailureAddress); } @@ -168,7 +172,8 @@ TEST_F(CrashHandlerAPITest, InvalidFreeNoMetadata) { EXPECT_TRUE(__gwp_asan_error_is_mine(&State)); EXPECT_EQ(Error::INVALID_FREE, __gwp_asan_diagnose_error(&State, Metadata, 0x0)); - EXPECT_EQ(FailureAddress, __gwp_asan_get_internal_crash_address(&State)); + EXPECT_EQ(FailureAddress, + __gwp_asan_get_internal_crash_address(&State, InternalFaultAddr)); EXPECT_EQ(nullptr, __gwp_asan_get_metadata(&State, Metadata, FailureAddress)); } @@ -180,7 +185,7 @@ TEST_F(CrashHandlerAPITest, UseAfterFree) { EXPECT_TRUE(__gwp_asan_error_is_mine(&State, FailureAddress)); EXPECT_EQ(Error::USE_AFTER_FREE, __gwp_asan_diagnose_error(&State, Metadata, FailureAddress)); - EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State)); + EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State, FailureAddress)); checkMetadata(Index, FailureAddress); } @@ -192,7 +197,7 @@ TEST_F(CrashHandlerAPITest, BufferOverflow) { EXPECT_TRUE(__gwp_asan_error_is_mine(&State, FailureAddress)); EXPECT_EQ(Error::BUFFER_OVERFLOW, __gwp_asan_diagnose_error(&State, Metadata, FailureAddress)); - EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State)); + EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State, FailureAddress)); checkMetadata(Index, FailureAddress); } @@ -204,6 +209,6 @@ TEST_F(CrashHandlerAPITest, BufferUnderflow) { EXPECT_TRUE(__gwp_asan_error_is_mine(&State, FailureAddress)); EXPECT_EQ(Error::BUFFER_UNDERFLOW, __gwp_asan_diagnose_error(&State, Metadata, FailureAddress)); - EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State)); + EXPECT_EQ(0u, __gwp_asan_get_internal_crash_address(&State, FailureAddress)); checkMetadata(Index, FailureAddress); } diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/harness.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/harness.cpp index e668c73057f..ccad80ebdaa 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/harness.cpp +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/harness.cpp @@ -16,3 +16,21 @@ bool OnlyOnce() { } } // namespace test } // namespace gwp_asan + +// Optnone to ensure that the calls to these functions are not optimized away, +// as we're looking for them in the backtraces. +__attribute__((optnone)) char * +AllocateMemory(gwp_asan::GuardedPoolAllocator &GPA) { + return static_cast(GPA.allocate(1)); +} +__attribute__((optnone)) void +DeallocateMemory(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr) { + GPA.deallocate(Ptr); +} +__attribute__((optnone)) void +DeallocateMemory2(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr) { + GPA.deallocate(Ptr); +} +__attribute__((optnone)) void TouchMemory(void *Ptr) { + *(reinterpret_cast(Ptr)) = 7; +} diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/harness.h b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/harness.h index ed91e642de7..c8f643dbab9 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/harness.h +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/harness.h @@ -14,9 +14,11 @@ #if defined(__Fuchsia__) #include using Test = ::zxtest::Test; +template using TestWithParam = ::zxtest::TestWithParam; #else #include "gtest/gtest.h" using Test = ::testing::Test; +template using TestWithParam = ::testing::TestWithParam; #endif #include "gwp_asan/guarded_pool_allocator.h" @@ -39,6 +41,11 @@ bool OnlyOnce(); }; // namespace test }; // namespace gwp_asan +char *AllocateMemory(gwp_asan::GuardedPoolAllocator &GPA); +void DeallocateMemory(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr); +void DeallocateMemory2(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr); +void TouchMemory(void *Ptr); + class DefaultGuardedPoolAllocator : public Test { public: void SetUp() override { @@ -81,7 +88,8 @@ protected: MaxSimultaneousAllocations; }; -class BacktraceGuardedPoolAllocator : public Test { +class BacktraceGuardedPoolAllocator + : public TestWithParam { public: void SetUp() override { gwp_asan::options::Options Opts; @@ -91,10 +99,19 @@ public: Opts.InstallForkHandlers = gwp_asan::test::OnlyOnce(); GPA.init(Opts); + // In recoverable mode, capture GWP-ASan logs to an internal buffer so that + // we can search it in unit tests. For non-recoverable tests, the default + // buffer is fine, as any tests should be EXPECT_DEATH()'d. + Recoverable = GetParam(); + gwp_asan::Printf_t PrintfFunction = PrintfToBuffer; + GetOutputBuffer().clear(); + if (!Recoverable) + PrintfFunction = gwp_asan::test::getPrintfFunction(); + gwp_asan::segv_handler::installSignalHandlers( - &GPA, gwp_asan::test::getPrintfFunction(), - gwp_asan::backtrace::getPrintBacktraceFunction(), - gwp_asan::backtrace::getSegvBacktraceFunction()); + &GPA, PrintfFunction, gwp_asan::backtrace::getPrintBacktraceFunction(), + gwp_asan::backtrace::getSegvBacktraceFunction(), + /* Recoverable */ Recoverable); } void TearDown() override { @@ -103,7 +120,23 @@ public: } protected: + static std::string &GetOutputBuffer() { + static std::string Buffer; + return Buffer; + } + + __attribute__((format(printf, 1, 2))) static void + PrintfToBuffer(const char *Format, ...) { + va_list AP; + va_start(AP, Format); + char Buffer[8192]; + vsnprintf(Buffer, sizeof(Buffer), Format, AP); + GetOutputBuffer() += Buffer; + va_end(AP); + } + gwp_asan::GuardedPoolAllocator GPA; + bool Recoverable; }; // https://github.com/google/googletest/blob/master/docs/advanced.md#death-tests-and-threads diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/iterate.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/iterate.cpp index 2b8635d5b36..49953f33abf 100644 --- a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/iterate.cpp +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/iterate.cpp @@ -8,6 +8,7 @@ #include "gwp_asan/tests/harness.h" +#include #include #include diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/tests/recoverable.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/recoverable.cpp new file mode 100644 index 00000000000..a4c5c3f5961 --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/gwp_asan/tests/recoverable.cpp @@ -0,0 +1,210 @@ +//===-- recoverable.cpp -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include +#include + +#include "gwp_asan/common.h" +#include "gwp_asan/crash_handler.h" +#include "gwp_asan/tests/harness.h" + +void CheckOnlyOneGwpAsanCrash(const std::string &OutputBuffer) { + const char *kGwpAsanErrorString = "GWP-ASan detected a memory error"; + size_t FirstIndex = OutputBuffer.find(kGwpAsanErrorString); + ASSERT_NE(FirstIndex, std::string::npos) << "Didn't detect a GWP-ASan crash"; + ASSERT_EQ(OutputBuffer.find(kGwpAsanErrorString, FirstIndex + 1), + std::string::npos) + << "Detected more than one GWP-ASan crash:\n" + << OutputBuffer; +} + +TEST_P(BacktraceGuardedPoolAllocator, MultipleDoubleFreeOnlyOneOutput) { + SCOPED_TRACE(""); + void *Ptr = AllocateMemory(GPA); + DeallocateMemory(GPA, Ptr); + // First time should generate a crash report. + DeallocateMemory(GPA, Ptr); + CheckOnlyOneGwpAsanCrash(GetOutputBuffer()); + ASSERT_NE(std::string::npos, GetOutputBuffer().find("Double Free")); + + // Ensure the crash is only reported once. + GetOutputBuffer().clear(); + for (size_t i = 0; i < 100; ++i) { + DeallocateMemory(GPA, Ptr); + ASSERT_TRUE(GetOutputBuffer().empty()); + } +} + +TEST_P(BacktraceGuardedPoolAllocator, MultipleInvalidFreeOnlyOneOutput) { + SCOPED_TRACE(""); + char *Ptr = static_cast(AllocateMemory(GPA)); + // First time should generate a crash report. + DeallocateMemory(GPA, Ptr + 1); + CheckOnlyOneGwpAsanCrash(GetOutputBuffer()); + ASSERT_NE(std::string::npos, GetOutputBuffer().find("Invalid (Wild) Free")); + + // Ensure the crash is only reported once. + GetOutputBuffer().clear(); + for (size_t i = 0; i < 100; ++i) { + DeallocateMemory(GPA, Ptr + 1); + ASSERT_TRUE(GetOutputBuffer().empty()); + } +} + +TEST_P(BacktraceGuardedPoolAllocator, MultipleUseAfterFreeOnlyOneOutput) { + SCOPED_TRACE(""); + void *Ptr = AllocateMemory(GPA); + DeallocateMemory(GPA, Ptr); + // First time should generate a crash report. + TouchMemory(Ptr); + ASSERT_NE(std::string::npos, GetOutputBuffer().find("Use After Free")); + + // Ensure the crash is only reported once. + GetOutputBuffer().clear(); + for (size_t i = 0; i < 100; ++i) { + TouchMemory(Ptr); + ASSERT_TRUE(GetOutputBuffer().empty()); + } +} + +TEST_P(BacktraceGuardedPoolAllocator, MultipleBufferOverflowOnlyOneOutput) { + SCOPED_TRACE(""); + char *Ptr = static_cast(AllocateMemory(GPA)); + // First time should generate a crash report. + TouchMemory(Ptr - 16); + TouchMemory(Ptr + 16); + CheckOnlyOneGwpAsanCrash(GetOutputBuffer()); + if (GetOutputBuffer().find("Buffer Overflow") == std::string::npos && + GetOutputBuffer().find("Buffer Underflow") == std::string::npos) + FAIL() << "Failed to detect buffer underflow/overflow:\n" + << GetOutputBuffer(); + + // Ensure the crash is only reported once. + GetOutputBuffer().clear(); + for (size_t i = 0; i < 100; ++i) { + TouchMemory(Ptr - 16); + TouchMemory(Ptr + 16); + ASSERT_TRUE(GetOutputBuffer().empty()) << GetOutputBuffer(); + } +} + +TEST_P(BacktraceGuardedPoolAllocator, OneDoubleFreeOneUseAfterFree) { + SCOPED_TRACE(""); + void *Ptr = AllocateMemory(GPA); + DeallocateMemory(GPA, Ptr); + // First time should generate a crash report. + DeallocateMemory(GPA, Ptr); + CheckOnlyOneGwpAsanCrash(GetOutputBuffer()); + ASSERT_NE(std::string::npos, GetOutputBuffer().find("Double Free")); + + // Ensure the crash is only reported once. + GetOutputBuffer().clear(); + for (size_t i = 0; i < 100; ++i) { + DeallocateMemory(GPA, Ptr); + ASSERT_TRUE(GetOutputBuffer().empty()); + } +} + +// We use double-free to detect that each slot can generate as single error. +// Use-after-free would also be acceptable, but buffer-overflow wouldn't be, as +// the random left/right alignment means that one right-overflow can disable +// page protections, and a subsequent left-overflow of a slot that's on the +// right hand side may not trap. +TEST_P(BacktraceGuardedPoolAllocator, OneErrorReportPerSlot) { + SCOPED_TRACE(""); + std::vector Ptrs; + for (size_t i = 0; i < GPA.getAllocatorState()->MaxSimultaneousAllocations; + ++i) { + void *Ptr = AllocateMemory(GPA); + ASSERT_NE(Ptr, nullptr); + Ptrs.push_back(Ptr); + DeallocateMemory(GPA, Ptr); + DeallocateMemory(GPA, Ptr); + CheckOnlyOneGwpAsanCrash(GetOutputBuffer()); + ASSERT_NE(std::string::npos, GetOutputBuffer().find("Double Free")); + // Ensure the crash from this slot is only reported once. + GetOutputBuffer().clear(); + DeallocateMemory(GPA, Ptr); + ASSERT_TRUE(GetOutputBuffer().empty()); + // Reset the buffer, as we're gonna move to the next allocation. + GetOutputBuffer().clear(); + } + + // All slots should have been used. No further errors should occur. + for (size_t i = 0; i < 100; ++i) + ASSERT_EQ(AllocateMemory(GPA), nullptr); + for (void *Ptr : Ptrs) { + DeallocateMemory(GPA, Ptr); + TouchMemory(Ptr); + } + ASSERT_TRUE(GetOutputBuffer().empty()); +} + +void singleAllocThrashTask(gwp_asan::GuardedPoolAllocator *GPA, + std::atomic *StartingGun, + unsigned NumIterations, unsigned Job, char *Ptr) { + while (!*StartingGun) { + // Wait for starting gun. + } + + for (unsigned i = 0; i < NumIterations; ++i) { + switch (Job) { + case 0: + DeallocateMemory(*GPA, Ptr); + break; + case 1: + DeallocateMemory(*GPA, Ptr + 1); + break; + case 2: + TouchMemory(Ptr); + break; + case 3: + TouchMemory(Ptr - 16); + TouchMemory(Ptr + 16); + break; + default: + __builtin_trap(); + } + } +} + +void runInterThreadThrashingSingleAlloc(unsigned NumIterations, + gwp_asan::GuardedPoolAllocator *GPA) { + std::atomic StartingGun{false}; + std::vector Threads; + constexpr unsigned kNumThreads = 4; + if (std::thread::hardware_concurrency() < kNumThreads) { + GTEST_SKIP() << "Not enough threads to run this test"; + } + + char *Ptr = static_cast(AllocateMemory(*GPA)); + + for (unsigned i = 0; i < kNumThreads; ++i) { + Threads.emplace_back(singleAllocThrashTask, GPA, &StartingGun, + NumIterations, i, Ptr); + } + + StartingGun = true; + + for (auto &T : Threads) + T.join(); +} + +TEST_P(BacktraceGuardedPoolAllocator, InterThreadThrashingSingleAlloc) { + SCOPED_TRACE(""); + constexpr unsigned kNumIterations = 100000; + runInterThreadThrashingSingleAlloc(kNumIterations, &GPA); + CheckOnlyOneGwpAsanCrash(GetOutputBuffer()); +} + +INSTANTIATE_TEST_SUITE_P(RecoverableTests, BacktraceGuardedPoolAllocator, + /* Recoverable */ testing::Values(true)); diff --git a/gnu/llvm/compiler-rt/lib/hwasan/CMakeLists.txt b/gnu/llvm/compiler-rt/lib/hwasan/CMakeLists.txt index d65c9b843c1..1b5775d9435 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/lib/hwasan/CMakeLists.txt @@ -15,8 +15,11 @@ set(HWASAN_RTL_SOURCES hwasan_memintrinsics.cpp hwasan_poisoning.cpp hwasan_report.cpp - hwasan_setjmp.S + hwasan_setjmp_aarch64.S + hwasan_setjmp_riscv64.S + hwasan_setjmp_x86_64.S hwasan_tag_mismatch_aarch64.S + hwasan_tag_mismatch_riscv64.S hwasan_thread.cpp hwasan_thread_list.cpp hwasan_type_test.cpp @@ -26,6 +29,10 @@ set(HWASAN_RTL_CXX_SOURCES hwasan_new_delete.cpp ) +set(HWASAN_RTL_PREINIT_SOURCES + hwasan_preinit.cpp + ) + set(HWASAN_RTL_HEADERS hwasan.h hwasan_allocator.h @@ -56,6 +63,9 @@ append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC HWASAN_RTL_CFLAGS) # Prevent clang from generating libc calls. append_list_if(COMPILER_RT_HAS_FFREESTANDING_FLAG -ffreestanding HWASAN_RTL_CFLAGS) +# Too many existing bugs, needs cleanup. +append_list_if(COMPILER_RT_HAS_WNO_FORMAT -Wno-format HWASAN_RTL_CFLAGS) + set(HWASAN_DYNAMIC_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS}) if(ANDROID) @@ -71,7 +81,10 @@ append_list_if(COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC -ftls-model=initial-exec HWASAN_DYNAMIC_CFLAGS) append_list_if(MSVC /DEBUG HWASAN_DYNAMIC_LINK_FLAGS) -set(HWASAN_DYNAMIC_LIBS ${SANITIZER_CXX_ABI_LIBRARIES} ${SANITIZER_COMMON_LINK_LIBS}) +set(HWASAN_DYNAMIC_LIBS + ${COMPILER_RT_UNWINDER_LINK_LIBS} + ${SANITIZER_CXX_ABI_LIBRARIES} + ${SANITIZER_COMMON_LINK_LIBS}) append_list_if(COMPILER_RT_HAS_LIBDL dl HWASAN_DYNAMIC_LIBS) append_list_if(COMPILER_RT_HAS_LIBRT rt HWASAN_DYNAMIC_LIBS) @@ -99,6 +112,12 @@ add_compiler_rt_object_libraries(RTHwasan_dynamic ADDITIONAL_HEADERS ${HWASAN_RTL_HEADERS} CFLAGS ${HWASAN_DYNAMIC_CFLAGS} DEFS ${HWASAN_DEFINITIONS}) +add_compiler_rt_object_libraries(RTHwasan_preinit + ARCHS ${HWASAN_SUPPORTED_ARCH} + SOURCES ${HWASAN_RTL_PREINIT_SOURCES} + ADDITIONAL_HEADERS ${HWASAN_RTL_HEADERS} + CFLAGS ${HWASAN_RTL_CFLAGS} + DEFS ${HWASAN_DEFINITIONS}) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp "") add_compiler_rt_object_libraries(RTHwasan_dynamic_version_script_dummy @@ -139,11 +158,13 @@ function(add_hwasan_runtimes arch use_aliases) STATIC ARCHS ${arch} OBJECT_LIBS ${hwasan_object_lib} + RTHwasan_preinit RTInterception RTSanitizerCommon RTSanitizerCommonLibc RTSanitizerCommonCoverage RTSanitizerCommonSymbolizer + RTLSanCommon RTUbsan CFLAGS ${hwasan_rtl_flags} PARENT_TARGET hwasan) @@ -180,6 +201,7 @@ function(add_hwasan_runtimes arch use_aliases) RTSanitizerCommonLibc RTSanitizerCommonCoverage RTSanitizerCommonSymbolizer + RTLSanCommon RTUbsan RTUbsan_cxx # The only purpose of RTHWAsan_dynamic_version_script_dummy is to @@ -214,6 +236,13 @@ foreach(arch ${HWASAN_SUPPORTED_ARCH}) endif() endforeach() +add_compiler_rt_runtime(clang_rt.hwasan-preinit + STATIC + ARCHS ${HWASAN_SUPPORTED_ARCH} + OBJECT_LIBS RTHwasan_preinit + CFLAGS ${HWASAN_RTL_CFLAGS} + PARENT_TARGET hwasan) + add_compiler_rt_resource_file(hwasan_ignorelist hwasan_ignorelist.txt hwasan) add_subdirectory("scripts") diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan.cpp index cbe0dee66dc..cdf231c2547 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan.cpp +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan.cpp @@ -16,6 +16,7 @@ #include "hwasan_checks.h" #include "hwasan_dynamic_shadow.h" #include "hwasan_globals.h" +#include "hwasan_mapping.h" #include "hwasan_poisoning.h" #include "hwasan_report.h" #include "hwasan_thread.h" @@ -24,6 +25,7 @@ #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flag_parser.h" #include "sanitizer_common/sanitizer_flags.h" +#include "sanitizer_common/sanitizer_interface_internal.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_procmaps.h" #include "sanitizer_common/sanitizer_stackdepot.h" @@ -84,6 +86,8 @@ static void InitializeFlags() { cf.clear_shadow_mmap_threshold = 4096 * (SANITIZER_ANDROID ? 2 : 8); // Sigtrap is used in error reporting. cf.handle_sigtrap = kHandleSignalExclusive; + // FIXME: enable once all false positives have been fixed. + cf.detect_leaks = false; #if SANITIZER_ANDROID // Let platform handle other signals. It is better at reporting them then we @@ -104,6 +108,15 @@ static void InitializeFlags() { RegisterHwasanFlags(&parser, f); RegisterCommonFlags(&parser); +#if CAN_SANITIZE_LEAKS + __lsan::Flags *lf = __lsan::flags(); + lf->SetDefaults(); + + FlagParser lsan_parser; + __lsan::RegisterLsanFlags(&lsan_parser, lf); + RegisterCommonFlags(&lsan_parser); +#endif + #if HWASAN_CONTAINS_UBSAN __ubsan::Flags *uf = __ubsan::flags(); uf->SetDefaults(); @@ -122,6 +135,9 @@ static void InitializeFlags() { #endif parser.ParseStringFromEnv("HWASAN_OPTIONS"); +#if CAN_SANITIZE_LEAKS + lsan_parser.ParseStringFromEnv("LSAN_OPTIONS"); +#endif #if HWASAN_CONTAINS_UBSAN ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS"); #endif @@ -131,6 +147,12 @@ static void InitializeFlags() { if (Verbosity()) ReportUnrecognizedFlags(); if (common_flags()->help) parser.PrintFlagDescriptions(); + // Flag validation: + if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) { + Report("%s: detect_leaks is not supported on this platform.\n", + SanitizerToolName); + Die(); + } } static void CheckUnwind() { @@ -141,7 +163,7 @@ static void CheckUnwind() { static void HwasanFormatMemoryUsage(InternalScopedString &s) { HwasanThreadList &thread_list = hwasanThreadList(); auto thread_stats = thread_list.GetThreadStats(); - auto *sds = StackDepotGetStats(); + auto sds = StackDepotGetStats(); AllocatorStatCounters asc; GetAllocatorStats(asc); s.append( @@ -151,7 +173,7 @@ static void HwasanFormatMemoryUsage(InternalScopedString &s) { internal_getpid(), GetRSS(), thread_stats.n_live_threads, thread_stats.total_stack_size, thread_stats.n_live_threads * thread_list.MemoryUsedPerThread(), - sds->allocated, sds->n_uniq_ids, asc[AllocatorStatMapped]); + sds.allocated, sds.n_uniq_ids, asc[AllocatorStatMapped]); } #if SANITIZER_ANDROID @@ -216,8 +238,8 @@ void HandleTagMismatch(AccessInfo ai, uptr pc, uptr frame, void *uc, registers_frame); } -void HwasanTagMismatch(uptr addr, uptr access_info, uptr *registers_frame, - size_t outsize) { +void HwasanTagMismatch(uptr addr, uptr pc, uptr frame, uptr access_info, + uptr *registers_frame, size_t outsize) { __hwasan::AccessInfo ai; ai.is_store = access_info & 0x10; ai.is_load = !ai.is_store; @@ -228,9 +250,7 @@ void HwasanTagMismatch(uptr addr, uptr access_info, uptr *registers_frame, else ai.size = 1 << (access_info & 0xf); - HandleTagMismatch(ai, (uptr)__builtin_return_address(0), - (uptr)__builtin_frame_address(0), nullptr, registers_frame); - __builtin_unreachable(); + HandleTagMismatch(ai, pc, frame, nullptr, registers_frame); } Thread *GetCurrentThread() { @@ -319,7 +339,7 @@ void __hwasan_init_static() { InitializeSingleGlobal(global); } -void __hwasan_init() { +__attribute__((constructor(0))) void __hwasan_init() { CHECK(!hwasan_init_is_running); if (hwasan_inited) return; hwasan_init_is_running = 1; @@ -340,11 +360,17 @@ void __hwasan_init() { DisableCoreDumperIfNecessary(); InitInstrumentation(); - InitLoadedGlobals(); + if constexpr (!SANITIZER_FUCHSIA) { + // Fuchsia's libc provides a hook (__sanitizer_module_loaded) that runs on + // the startup path which calls into __hwasan_library_loaded on all + // initially loaded modules, so explicitly registering the globals here + // isn't needed. + InitLoadedGlobals(); + } // Needs to be called here because flags()->random_tags might not have been // initialized when InitInstrumentation() was called. - GetCurrentThread()->InitRandomState(); + GetCurrentThread()->EnsureRandomStateInited(); SetPrintfAndReportCallback(AppendToErrorMessageBuffer); // This may call libc -> needs initialized shadow. @@ -360,11 +386,24 @@ void __hwasan_init() { HwasanTSDThreadInit(); HwasanAllocatorInit(); + HwasanInstallAtForkHandler(); + + if (CAN_SANITIZE_LEAKS) { + __lsan::InitCommonLsan(); + InstallAtExitCheckLeaks(); + } #if HWASAN_CONTAINS_UBSAN __ubsan::InitAsPlugin(); #endif + if (CAN_SANITIZE_LEAKS) { + __lsan::ScopedInterceptorDisabler disabler; + Symbolizer::LateInitialize(); + } else { + Symbolizer::LateInitialize(); + } + VPrintf(1, "HWAddressSanitizer init done\n"); hwasan_init_is_running = 0; @@ -390,8 +429,15 @@ void __hwasan_print_shadow(const void *p, uptr sz) { uptr shadow_last = MemToShadow(ptr_raw + sz - 1); Printf("HWASan shadow map for %zx .. %zx (pointer tag %x)\n", ptr_raw, ptr_raw + sz, GetTagFromPointer((uptr)p)); - for (uptr s = shadow_first; s <= shadow_last; ++s) - Printf(" %zx: %x\n", ShadowToMem(s), *(tag_t *)s); + for (uptr s = shadow_first; s <= shadow_last; ++s) { + tag_t mem_tag = *reinterpret_cast(s); + uptr granule_addr = ShadowToMem(s); + if (mem_tag && mem_tag < kShadowAlignment) + Printf(" %zx: %02x(%02x)\n", granule_addr, mem_tag, + *reinterpret_cast(granule_addr + kShadowAlignment - 1)); + else + Printf(" %zx: %02x\n", granule_addr, mem_tag); + } } sptr __hwasan_test_shadow(const void *p, uptr sz) { @@ -566,6 +612,12 @@ u8 __hwasan_generate_tag() { return t->GenerateRandomTag(); } +void __hwasan_add_frame_record(u64 frame_record_info) { + Thread *t = GetCurrentThread(); + if (t) + t->stack_allocations()->push(frame_record_info); +} + #if !SANITIZER_SUPPORTS_WEAK_HOOKS extern "C" { SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE @@ -584,7 +636,9 @@ void __sanitizer_print_stack_trace() { // rest of the mismatch handling code (C++). void __hwasan_tag_mismatch4(uptr addr, uptr access_info, uptr *registers_frame, size_t outsize) { - __hwasan::HwasanTagMismatch(addr, access_info, registers_frame, outsize); + __hwasan::HwasanTagMismatch(addr, (uptr)__builtin_return_address(0), + (uptr)__builtin_frame_address(0), access_info, + registers_frame, outsize); } } // extern "C" diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan.h b/gnu/llvm/compiler-rt/lib/hwasan/hwasan.h index 7338b696ad3..c3d71a28142 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan.h +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan.h @@ -107,6 +107,8 @@ void InitThreads(); void InitializeInterceptors(); void HwasanAllocatorInit(); +void HwasanAllocatorLock(); +void HwasanAllocatorUnlock(); void *hwasan_malloc(uptr size, StackTrace *stack); void *hwasan_calloc(uptr nmemb, uptr size, StackTrace *stack); @@ -140,6 +142,10 @@ void HwasanAtExit(); void HwasanOnDeadlySignal(int signo, void *info, void *context); +void HwasanInstallAtForkHandler(); + +void InstallAtExitCheckLeaks(); + void UpdateMemoryUsage(); void AppendToErrorMessageBuffer(const char *buffer); @@ -163,45 +169,46 @@ void HandleTagMismatch(AccessInfo ai, uptr pc, uptr frame, void *uc, // This dispatches to HandleTagMismatch but sets up the AccessInfo, program // counter, and frame pointer. -void HwasanTagMismatch(uptr addr, uptr access_info, uptr *registers_frame, - size_t outsize); +void HwasanTagMismatch(uptr addr, uptr pc, uptr frame, uptr access_info, + uptr *registers_frame, size_t outsize); } // namespace __hwasan -#define HWASAN_MALLOC_HOOK(ptr, size) \ - do { \ - if (&__sanitizer_malloc_hook) { \ - __sanitizer_malloc_hook(ptr, size); \ - } \ - RunMallocHooks(ptr, size); \ - } while (false) -#define HWASAN_FREE_HOOK(ptr) \ - do { \ - if (&__sanitizer_free_hook) { \ - __sanitizer_free_hook(ptr); \ - } \ - RunFreeHooks(ptr); \ - } while (false) - -#if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__) +#if HWASAN_WITH_INTERCEPTORS // For both bionic and glibc __sigset_t is an unsigned long. typedef unsigned long __hw_sigset_t; // Setjmp and longjmp implementations are platform specific, and hence the -// interception code is platform specific too. As yet we've only implemented -// the interception for AArch64. -typedef unsigned long long __hw_register_buf[22]; +// interception code is platform specific too. +# if defined(__aarch64__) +constexpr size_t kHwRegisterBufSize = 22; +# elif defined(__x86_64__) +constexpr size_t kHwRegisterBufSize = 8; +# elif SANITIZER_RISCV64 +// saving PC, 12 int regs, sp, 12 fp regs +# ifndef __riscv_float_abi_soft +constexpr size_t kHwRegisterBufSize = 1 + 12 + 1 + 12; +# else +constexpr size_t kHwRegisterBufSize = 1 + 12 + 1; +# endif +# endif +typedef unsigned long long __hw_register_buf[kHwRegisterBufSize]; struct __hw_jmp_buf_struct { // NOTE: The machine-dependent definition of `__sigsetjmp' // assume that a `__hw_jmp_buf' begins with a `__hw_register_buf' and that // `__mask_was_saved' follows it. Do not move these members or add others // before it. + // + // We add a __magic field to our struct to catch cases where libc's setjmp + // populated the jmp_buf instead of our interceptor. __hw_register_buf __jmpbuf; // Calling environment. - int __mask_was_saved; // Saved the signal mask? + unsigned __mask_was_saved : 1; // Saved the signal mask? + unsigned __magic : 31; // Used to distinguish __hw_jmp_buf from jmp_buf. __hw_sigset_t __saved_mask; // Saved signal mask. }; typedef struct __hw_jmp_buf_struct __hw_jmp_buf[1]; typedef struct __hw_jmp_buf_struct __hw_sigjmp_buf[1]; -#endif // HWASAN_WITH_INTERCEPTORS && __aarch64__ +constexpr unsigned kHwJmpBufMagic = 0x248ACE77; +#endif // HWASAN_WITH_INTERCEPTORS #define ENSURE_HWASAN_INITED() \ do { \ diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp index 6c2a6077866..9cd82dbabd1 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp @@ -14,28 +14,21 @@ #include "hwasan.h" #include "interception/interception.h" +#include "sanitizer_common/sanitizer_allocator_dlsym.h" #include "sanitizer_common/sanitizer_allocator_interface.h" #include "sanitizer_common/sanitizer_tls_get_addr.h" -using namespace __hwasan; +#if !SANITIZER_FUCHSIA -static uptr allocated_for_dlsym; -static const uptr kDlsymAllocPoolSize = 1024; -static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize]; +using namespace __hwasan; -static bool IsInDlsymAllocPool(const void *ptr) { - uptr off = (uptr)ptr - (uptr)alloc_memory_for_dlsym; - return off < sizeof(alloc_memory_for_dlsym); -} +struct DlsymAlloc : public DlSymAllocator { + static bool UseImpl() { return !hwasan_inited; } +}; -static void *AllocateFromLocalPool(uptr size_in_bytes) { - uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize; - void *mem = (void *)&alloc_memory_for_dlsym[allocated_for_dlsym]; - allocated_for_dlsym += size_in_words; - CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize); - return mem; -} +extern "C" { +SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_posix_memalign(void **memptr, uptr alignment, uptr size) { GET_MALLOC_STACK_TRACE; CHECK_NE(memptr, 0); @@ -43,16 +36,19 @@ int __sanitizer_posix_memalign(void **memptr, uptr alignment, uptr size) { return res; } +SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_memalign(uptr alignment, uptr size) { GET_MALLOC_STACK_TRACE; return hwasan_memalign(alignment, size, &stack); } +SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_aligned_alloc(uptr alignment, uptr size) { GET_MALLOC_STACK_TRACE; return hwasan_aligned_alloc(alignment, size, &stack); } +SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer___libc_memalign(uptr alignment, uptr size) { GET_MALLOC_STACK_TRACE; void *ptr = hwasan_memalign(alignment, size, &stack); @@ -61,87 +57,92 @@ void *__sanitizer___libc_memalign(uptr alignment, uptr size) { return ptr; } +SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_valloc(uptr size) { GET_MALLOC_STACK_TRACE; return hwasan_valloc(size, &stack); } +SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_pvalloc(uptr size) { GET_MALLOC_STACK_TRACE; return hwasan_pvalloc(size, &stack); } +SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_free(void *ptr) { - GET_MALLOC_STACK_TRACE; - if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr))) + if (!ptr) return; + if (DlsymAlloc::PointerIsMine(ptr)) + return DlsymAlloc::Free(ptr); + GET_MALLOC_STACK_TRACE; hwasan_free(ptr, &stack); } +SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cfree(void *ptr) { - GET_MALLOC_STACK_TRACE; - if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr))) + if (!ptr) return; + if (DlsymAlloc::PointerIsMine(ptr)) + return DlsymAlloc::Free(ptr); + GET_MALLOC_STACK_TRACE; hwasan_free(ptr, &stack); } +SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_malloc_usable_size(const void *ptr) { return __sanitizer_get_allocated_size(ptr); } +SANITIZER_INTERFACE_ATTRIBUTE struct __sanitizer_struct_mallinfo __sanitizer_mallinfo() { __sanitizer_struct_mallinfo sret; internal_memset(&sret, 0, sizeof(sret)); return sret; } +SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_mallopt(int cmd, int value) { return 0; } +SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_malloc_stats(void) { // FIXME: implement, but don't call REAL(malloc_stats)! } +SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_calloc(uptr nmemb, uptr size) { + if (DlsymAlloc::Use()) + return DlsymAlloc::Callocate(nmemb, size); GET_MALLOC_STACK_TRACE; - if (UNLIKELY(!hwasan_inited)) - // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. - return AllocateFromLocalPool(nmemb * size); return hwasan_calloc(nmemb, size, &stack); } +SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_realloc(void *ptr, uptr size) { + if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) + return DlsymAlloc::Realloc(ptr, size); GET_MALLOC_STACK_TRACE; - if (UNLIKELY(IsInDlsymAllocPool(ptr))) { - uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym; - uptr copy_size = Min(size, kDlsymAllocPoolSize - offset); - void *new_ptr; - if (UNLIKELY(!hwasan_inited)) { - new_ptr = AllocateFromLocalPool(copy_size); - } else { - copy_size = size; - new_ptr = hwasan_malloc(copy_size, &stack); - } - internal_memcpy(new_ptr, ptr, copy_size); - return new_ptr; - } return hwasan_realloc(ptr, size, &stack); } +SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_reallocarray(void *ptr, uptr nmemb, uptr size) { GET_MALLOC_STACK_TRACE; return hwasan_reallocarray(ptr, nmemb, size, &stack); } +SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_malloc(uptr size) { - GET_MALLOC_STACK_TRACE; if (UNLIKELY(!hwasan_init_is_running)) ENSURE_HWASAN_INITED(); - if (UNLIKELY(!hwasan_inited)) - // Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym. - return AllocateFromLocalPool(size); + if (DlsymAlloc::Use()) + return DlsymAlloc::Allocate(size); + GET_MALLOC_STACK_TRACE; return hwasan_malloc(size, &stack); } +} // extern "C" + #if HWASAN_WITH_INTERCEPTORS # define INTERCEPTOR_ALIAS(RET, FN, ARGS...) \ extern "C" SANITIZER_INTERFACE_ATTRIBUTE RET WRAP(FN)(ARGS) \ @@ -170,3 +171,5 @@ INTERCEPTOR_ALIAS(int, mallopt, int cmd, int value); INTERCEPTOR_ALIAS(void, malloc_stats, void); # endif #endif // #if HWASAN_WITH_INTERCEPTORS + +#endif // SANITIZER_FUCHSIA diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_allocator.cpp index ef6d4d6c767..325675ce122 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_allocator.cpp +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_allocator.cpp @@ -21,6 +21,7 @@ #include "hwasan_malloc_bisect.h" #include "hwasan_thread.h" #include "hwasan_report.h" +#include "lsan/lsan_common.h" namespace __hwasan { @@ -32,40 +33,34 @@ static atomic_uint8_t hwasan_allocator_tagging_enabled; static constexpr tag_t kFallbackAllocTag = 0xBB & kTagMask; static constexpr tag_t kFallbackFreeTag = 0xBC; -enum RightAlignMode { - kRightAlignNever, - kRightAlignSometimes, - kRightAlignAlways +enum { + // Either just allocated by underlying allocator, but AsanChunk is not yet + // ready, or almost returned to undelying allocator and AsanChunk is already + // meaningless. + CHUNK_INVALID = 0, + // The chunk is allocated and not yet freed. + CHUNK_ALLOCATED = 1, }; + // Initialized in HwasanAllocatorInit, an never changed. static ALIGNED(16) u8 tail_magic[kShadowAlignment - 1]; bool HwasanChunkView::IsAllocated() const { - return metadata_ && metadata_->alloc_context_id && - metadata_->get_requested_size(); -} - -// Aligns the 'addr' right to the granule boundary. -static uptr AlignRight(uptr addr, uptr requested_size) { - uptr tail_size = requested_size % kShadowAlignment; - if (!tail_size) return addr; - return addr + kShadowAlignment - tail_size; + return metadata_ && metadata_->IsAllocated(); } uptr HwasanChunkView::Beg() const { - if (metadata_ && metadata_->right_aligned) - return AlignRight(block_, metadata_->get_requested_size()); return block_; } uptr HwasanChunkView::End() const { return Beg() + UsedSize(); } uptr HwasanChunkView::UsedSize() const { - return metadata_->get_requested_size(); + return metadata_->GetRequestedSize(); } u32 HwasanChunkView::GetAllocStackId() const { - return metadata_->alloc_context_id; + return metadata_->GetAllocStackId(); } uptr HwasanChunkView::ActualSize() const { @@ -76,10 +71,53 @@ bool HwasanChunkView::FromSmallHeap() const { return allocator.FromPrimary(reinterpret_cast(block_)); } +bool HwasanChunkView::AddrIsInside(uptr addr) const { + return (addr >= Beg()) && (addr < Beg() + UsedSize()); +} + +inline void Metadata::SetAllocated(u32 stack, u64 size) { + Thread *t = GetCurrentThread(); + u64 context = t ? t->unique_id() : kMainTid; + context <<= 32; + context += stack; + requested_size_low = size & ((1ul << 32) - 1); + requested_size_high = size >> 32; + atomic_store(&alloc_context_id, context, memory_order_relaxed); + atomic_store(&chunk_state, CHUNK_ALLOCATED, memory_order_release); +} + +inline void Metadata::SetUnallocated() { + atomic_store(&chunk_state, CHUNK_INVALID, memory_order_release); + requested_size_low = 0; + requested_size_high = 0; + atomic_store(&alloc_context_id, 0, memory_order_relaxed); +} + +inline bool Metadata::IsAllocated() const { + return atomic_load(&chunk_state, memory_order_relaxed) == CHUNK_ALLOCATED && + GetRequestedSize(); +} + +inline u64 Metadata::GetRequestedSize() const { + return (static_cast(requested_size_high) << 32) + requested_size_low; +} + +inline u32 Metadata::GetAllocStackId() const { + return atomic_load(&alloc_context_id, memory_order_relaxed); +} + void GetAllocatorStats(AllocatorStatCounters s) { allocator.GetStats(s); } +inline void Metadata::SetLsanTag(__lsan::ChunkTag tag) { + lsan_tag = tag; +} + +inline __lsan::ChunkTag Metadata::GetLsanTag() const { + return static_cast<__lsan::ChunkTag>(lsan_tag); +} + uptr GetAliasRegionStart() { #if defined(HWASAN_ALIASING_MODE) constexpr uptr kAliasRegionOffset = 1ULL << (kTaggableRegionCheckShift - 1); @@ -107,6 +145,10 @@ void HwasanAllocatorInit() { tail_magic[i] = GetCurrentThread()->GenerateRandomTag(); } +void HwasanAllocatorLock() { allocator.ForceLock(); } + +void HwasanAllocatorUnlock() { allocator.ForceUnlock(); } + void AllocatorSwallowThreadLocalCache(AllocatorCache *cache) { allocator.SwallowCache(cache); } @@ -128,6 +170,11 @@ static void *HwasanAllocate(StackTrace *stack, uptr orig_size, uptr alignment, } ReportAllocationSizeTooBig(orig_size, kMaxAllowedMallocSize, stack); } + if (UNLIKELY(IsRssLimitExceeded())) { + if (AllocatorMayReturnNull()) + return nullptr; + ReportRssLimitExceeded(stack); + } alignment = Max(alignment, kShadowAlignment); uptr size = TaggedSize(orig_size); @@ -146,11 +193,6 @@ static void *HwasanAllocate(StackTrace *stack, uptr orig_size, uptr alignment, return nullptr; ReportOutOfMemory(size, stack); } - Metadata *meta = - reinterpret_cast(allocator.GetMetaData(allocated)); - meta->set_requested_size(orig_size); - meta->alloc_context_id = StackDepotPut(*stack); - meta->right_aligned = false; if (zeroise) { internal_memset(allocated, 0, size); } else if (flags()->max_malloc_fill_size > 0) { @@ -158,8 +200,11 @@ static void *HwasanAllocate(StackTrace *stack, uptr orig_size, uptr alignment, internal_memset(allocated, flags()->malloc_fill_byte, fill_size); } if (size != orig_size) { - internal_memcpy(reinterpret_cast(allocated) + orig_size, tail_magic, - size - orig_size - 1); + u8 *tail = reinterpret_cast(allocated) + orig_size; + uptr tail_length = size - orig_size; + internal_memcpy(tail, tail_magic, tail_length - 1); + // Short granule is excluded from magic tail, so we explicitly untag. + tail[tail_length - 1] = 0; } void *user_ptr = allocated; @@ -187,7 +232,14 @@ static void *HwasanAllocate(StackTrace *stack, uptr orig_size, uptr alignment, } } - HWASAN_MALLOC_HOOK(user_ptr, size); + Metadata *meta = + reinterpret_cast(allocator.GetMetaData(allocated)); +#if CAN_SANITIZE_LEAKS + meta->SetLsanTag(__lsan::DisabledInThisThread() ? __lsan::kIgnored + : __lsan::kDirectlyLeaked); +#endif + meta->SetAllocated(StackDepotPut(*stack), orig_size); + RunMallocHooks(user_ptr, size); return user_ptr; } @@ -201,24 +253,40 @@ static bool PointerAndMemoryTagsMatch(void *tagged_ptr) { return PossiblyShortTagMatches(mem_tag, tagged_uptr, 1); } +static bool CheckInvalidFree(StackTrace *stack, void *untagged_ptr, + void *tagged_ptr) { + // This function can return true if halt_on_error is false. + if (!MemIsApp(reinterpret_cast(untagged_ptr)) || + !PointerAndMemoryTagsMatch(tagged_ptr)) { + ReportInvalidFree(stack, reinterpret_cast(tagged_ptr)); + return true; + } + return false; +} + static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) { CHECK(tagged_ptr); - HWASAN_FREE_HOOK(tagged_ptr); + RunFreeHooks(tagged_ptr); - if (!PointerAndMemoryTagsMatch(tagged_ptr)) - ReportInvalidFree(stack, reinterpret_cast(tagged_ptr)); + bool in_taggable_region = + InTaggableRegion(reinterpret_cast(tagged_ptr)); + void *untagged_ptr = in_taggable_region ? UntagPtr(tagged_ptr) : tagged_ptr; + + if (CheckInvalidFree(stack, untagged_ptr, tagged_ptr)) + return; - void *untagged_ptr = InTaggableRegion(reinterpret_cast(tagged_ptr)) - ? UntagPtr(tagged_ptr) - : tagged_ptr; void *aligned_ptr = reinterpret_cast( RoundDownTo(reinterpret_cast(untagged_ptr), kShadowAlignment)); tag_t pointer_tag = GetTagFromPointer(reinterpret_cast(tagged_ptr)); Metadata *meta = reinterpret_cast(allocator.GetMetaData(aligned_ptr)); - uptr orig_size = meta->get_requested_size(); + if (!meta) { + ReportInvalidFree(stack, reinterpret_cast(tagged_ptr)); + return; + } + uptr orig_size = meta->GetRequestedSize(); u32 free_context_id = StackDepotPut(*stack); - u32 alloc_context_id = meta->alloc_context_id; + u32 alloc_context_id = meta->GetAllocStackId(); // Check tail magic. uptr tagged_size = TaggedSize(orig_size); @@ -228,13 +296,17 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) { CHECK_LT(tail_size, kShadowAlignment); void *tail_beg = reinterpret_cast( reinterpret_cast(aligned_ptr) + orig_size); - if (tail_size && internal_memcmp(tail_beg, tail_magic, tail_size)) + tag_t short_granule_memtag = *(reinterpret_cast( + reinterpret_cast(tail_beg) + tail_size)); + if (tail_size && + (internal_memcmp(tail_beg, tail_magic, tail_size) || + (in_taggable_region && pointer_tag != short_granule_memtag))) ReportTailOverwritten(stack, reinterpret_cast(tagged_ptr), orig_size, tail_magic); } - meta->set_requested_size(0); - meta->alloc_context_id = 0; + // TODO(kstoimenov): consider meta->SetUnallocated(free_context_id). + meta->SetUnallocated(); // This memory will not be reused by anyone else, so we are free to keep it // poisoned. Thread *t = GetCurrentThread(); @@ -243,8 +315,7 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) { Min(TaggedSize(orig_size), (uptr)flags()->max_free_fill_size); internal_memset(aligned_ptr, flags()->free_fill_byte, fill_size); } - if (InTaggableRegion(reinterpret_cast(tagged_ptr)) && - flags()->tag_in_free && malloc_bisect(stack, 0) && + if (in_taggable_region && flags()->tag_in_free && malloc_bisect(stack, 0) && atomic_load_relaxed(&hwasan_allocator_tagging_enabled)) { // Always store full 8-bit tags on free to maximize UAF detection. tag_t tag; @@ -278,18 +349,20 @@ static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) { static void *HwasanReallocate(StackTrace *stack, void *tagged_ptr_old, uptr new_size, uptr alignment) { - if (!PointerAndMemoryTagsMatch(tagged_ptr_old)) - ReportInvalidFree(stack, reinterpret_cast(tagged_ptr_old)); - + void *untagged_ptr_old = + InTaggableRegion(reinterpret_cast(tagged_ptr_old)) + ? UntagPtr(tagged_ptr_old) + : tagged_ptr_old; + if (CheckInvalidFree(stack, untagged_ptr_old, tagged_ptr_old)) + return nullptr; void *tagged_ptr_new = HwasanAllocate(stack, new_size, alignment, false /*zeroise*/); if (tagged_ptr_old && tagged_ptr_new) { - void *untagged_ptr_old = UntagPtr(tagged_ptr_old); Metadata *meta = reinterpret_cast(allocator.GetMetaData(untagged_ptr_old)); internal_memcpy( UntagPtr(tagged_ptr_new), untagged_ptr_old, - Min(new_size, static_cast(meta->get_requested_size()))); + Min(new_size, static_cast(meta->GetRequestedSize()))); HwasanDeallocate(stack, tagged_ptr_old); } return tagged_ptr_new; @@ -305,6 +378,8 @@ static void *HwasanCalloc(StackTrace *stack, uptr nmemb, uptr size) { } HwasanChunkView FindHeapChunkByAddress(uptr address) { + if (!allocator.PointerIsMine(reinterpret_cast(address))) + return HwasanChunkView(); void *block = allocator.GetBlockBegin(reinterpret_cast(address)); if (!block) return HwasanChunkView(); @@ -318,14 +393,8 @@ static uptr AllocationSize(const void *tagged_ptr) { if (!untagged_ptr) return 0; const void *beg = allocator.GetBlockBegin(untagged_ptr); Metadata *b = (Metadata *)allocator.GetMetaData(untagged_ptr); - if (b->right_aligned) { - if (beg != reinterpret_cast(RoundDownTo( - reinterpret_cast(untagged_ptr), kShadowAlignment))) - return 0; - } else { - if (beg != untagged_ptr) return 0; - } - return b->get_requested_size(); + if (beg != untagged_ptr) return 0; + return b->GetRequestedSize(); } void *hwasan_malloc(uptr size, StackTrace *stack) { @@ -416,6 +485,116 @@ void hwasan_free(void *ptr, StackTrace *stack) { } // namespace __hwasan +// --- Implementation of LSan-specific functions --- {{{1 +namespace __lsan { + +void LockAllocator() { + __hwasan::HwasanAllocatorLock(); +} + +void UnlockAllocator() { + __hwasan::HwasanAllocatorUnlock(); +} + +void GetAllocatorGlobalRange(uptr *begin, uptr *end) { + *begin = (uptr)&__hwasan::allocator; + *end = *begin + sizeof(__hwasan::allocator); +} + +uptr PointsIntoChunk(void *p) { + p = __hwasan::InTaggableRegion(reinterpret_cast(p)) ? UntagPtr(p) : p; + uptr addr = reinterpret_cast(p); + uptr chunk = + reinterpret_cast(__hwasan::allocator.GetBlockBeginFastLocked(p)); + if (!chunk) + return 0; + __hwasan::Metadata *metadata = reinterpret_cast<__hwasan::Metadata *>( + __hwasan::allocator.GetMetaData(reinterpret_cast(chunk))); + if (!metadata || !metadata->IsAllocated()) + return 0; + if (addr < chunk + metadata->GetRequestedSize()) + return chunk; + if (IsSpecialCaseOfOperatorNew0(chunk, metadata->GetRequestedSize(), addr)) + return chunk; + return 0; +} + +uptr GetUserBegin(uptr chunk) { + if (__hwasan::InTaggableRegion(chunk)) + CHECK_EQ(UntagAddr(chunk), chunk); + void *block = __hwasan::allocator.GetBlockBeginFastLocked( + reinterpret_cast(chunk)); + if (!block) + return 0; + __hwasan::Metadata *metadata = reinterpret_cast<__hwasan::Metadata *>( + __hwasan::allocator.GetMetaData(block)); + if (!metadata || !metadata->IsAllocated()) + return 0; + + return reinterpret_cast(block); +} + +LsanMetadata::LsanMetadata(uptr chunk) { + if (__hwasan::InTaggableRegion(chunk)) + CHECK_EQ(UntagAddr(chunk), chunk); + metadata_ = + chunk ? __hwasan::allocator.GetMetaData(reinterpret_cast(chunk)) + : nullptr; +} + +bool LsanMetadata::allocated() const { + if (!metadata_) + return false; + __hwasan::Metadata *m = reinterpret_cast<__hwasan::Metadata *>(metadata_); + return m->IsAllocated(); +} + +ChunkTag LsanMetadata::tag() const { + __hwasan::Metadata *m = reinterpret_cast<__hwasan::Metadata *>(metadata_); + return m->GetLsanTag(); +} + +void LsanMetadata::set_tag(ChunkTag value) { + __hwasan::Metadata *m = reinterpret_cast<__hwasan::Metadata *>(metadata_); + m->SetLsanTag(value); +} + +uptr LsanMetadata::requested_size() const { + __hwasan::Metadata *m = reinterpret_cast<__hwasan::Metadata *>(metadata_); + return m->GetRequestedSize(); +} + +u32 LsanMetadata::stack_trace_id() const { + __hwasan::Metadata *m = reinterpret_cast<__hwasan::Metadata *>(metadata_); + return m->GetAllocStackId(); +} + +void ForEachChunk(ForEachChunkCallback callback, void *arg) { + __hwasan::allocator.ForEachChunk(callback, arg); +} + +IgnoreObjectResult IgnoreObjectLocked(const void *p) { + p = __hwasan::InTaggableRegion(reinterpret_cast(p)) ? UntagPtr(p) : p; + uptr addr = reinterpret_cast(p); + uptr chunk = + reinterpret_cast(__hwasan::allocator.GetBlockBeginFastLocked(p)); + if (!chunk) + return kIgnoreObjectInvalid; + __hwasan::Metadata *metadata = reinterpret_cast<__hwasan::Metadata *>( + __hwasan::allocator.GetMetaData(reinterpret_cast(chunk))); + if (!metadata || !metadata->IsAllocated()) + return kIgnoreObjectInvalid; + if (addr >= chunk + metadata->GetRequestedSize()) + return kIgnoreObjectInvalid; + if (metadata->GetLsanTag() == kIgnored) + return kIgnoreObjectAlreadyIgnored; + + metadata->SetLsanTag(kIgnored); + return kIgnoreObjectSuccess; +} + +} // namespace __lsan + using namespace __hwasan; void __hwasan_enable_allocator_tagging() { diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_allocator.h b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_allocator.h index 35c3d6b4bf4..67982cad254 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_allocator.h +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_allocator.h @@ -17,6 +17,7 @@ #include "hwasan_interface_internal.h" #include "hwasan_mapping.h" #include "hwasan_poisoning.h" +#include "lsan/lsan_common.h" #include "sanitizer_common/sanitizer_allocator.h" #include "sanitizer_common/sanitizer_allocator_checks.h" #include "sanitizer_common/sanitizer_allocator_interface.h" @@ -24,25 +25,31 @@ #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_ring_buffer.h" -#if !defined(__aarch64__) && !defined(__x86_64__) -#error Unsupported platform +#if !defined(__aarch64__) && !defined(__x86_64__) && !(SANITIZER_RISCV64) +# error Unsupported platform #endif namespace __hwasan { struct Metadata { + private: + atomic_uint64_t alloc_context_id; u32 requested_size_low; - u32 requested_size_high : 31; - u32 right_aligned : 1; - u32 alloc_context_id; - u64 get_requested_size() { - return (static_cast(requested_size_high) << 32) + requested_size_low; - } - void set_requested_size(u64 size) { - requested_size_low = size & ((1ul << 32) - 1); - requested_size_high = size >> 32; - } + u16 requested_size_high; + atomic_uint8_t chunk_state; + u8 lsan_tag; + + public: + inline void SetAllocated(u32 stack, u64 size); + inline void SetUnallocated(); + + inline bool IsAllocated() const; + inline u64 GetRequestedSize() const; + inline u32 GetAllocStackId() const; + inline void SetLsanTag(__lsan::ChunkTag tag); + inline __lsan::ChunkTag GetLsanTag() const; }; +static_assert(sizeof(Metadata) == 16); struct HwasanMapUnmapCallback { void OnMap(uptr p, uptr size) const { UpdateMemoryUsage(); } @@ -88,7 +95,10 @@ class HwasanChunkView { uptr ActualSize() const; // Size allocated by the allocator. u32 GetAllocStackId() const; bool FromSmallHeap() const; + bool AddrIsInside(uptr addr) const; + private: + friend class __lsan::LsanMetadata; uptr block_; Metadata *const metadata_; }; diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_checks.h b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_checks.h index ab543ea88be..b0b37d7a2e2 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_checks.h +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_checks.h @@ -36,6 +36,15 @@ __attribute__((always_inline)) static void SigTrap(uptr p) { "int3\n" "nopl %c0(%%rax)\n" ::"n"(0x40 + X), "D"(p)); +#elif SANITIZER_RISCV64 + // Put pointer into x10 + // addiw contains immediate of 0x40 + X, where 0x40 is magic number and X + // encodes access size + register uptr x10 asm("x10") = p; + asm volatile( + "ebreak\n" + "addiw x0, x0, %1\n" ::"r"(x10), + "I"(0x40 + X)); #else // FIXME: not always sigill. __builtin_trap(); @@ -56,6 +65,14 @@ __attribute__((always_inline)) static void SigTrap(uptr p, uptr size) { "int3\n" "nopl %c0(%%rax)\n" ::"n"(0x40 + X), "D"(p), "S"(size)); +#elif SANITIZER_RISCV64 + // Put access size into x11 + register uptr x10 asm("x10") = p; + register uptr x11 asm("x11") = size; + asm volatile( + "ebreak\n" + "addiw x0, x0, %2\n" ::"r"(x10), + "r"(x11), "I"(0x40 + X)); #else __builtin_trap(); #endif @@ -71,7 +88,7 @@ __attribute__((always_inline, nodebug)) static bool PossiblyShortTagMatches( return false; if ((ptr & (kShadowAlignment - 1)) + sz > mem_tag) return false; -#ifndef __aarch64__ +#if !defined(__aarch64__) && !(SANITIZER_RISCV64) ptr = UntagAddr(ptr); #endif return *(u8 *)(ptr | (kShadowAlignment - 1)) == ptr_tag; diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_exceptions.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_exceptions.cpp index 169e7876cb5..c9968a5e360 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_exceptions.cpp +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_exceptions.cpp @@ -29,8 +29,8 @@ typedef _Unwind_Reason_Code PersonalityFn(int version, _Unwind_Action actions, // is statically linked and the sanitizer runtime and the program are linked // against different unwinders. The _Unwind_Context data structure is opaque so // it may be incompatible between unwinders. -typedef _Unwind_Word GetGRFn(_Unwind_Context* context, int index); -typedef _Unwind_Word GetCFAFn(_Unwind_Context* context); +typedef uintptr_t GetGRFn(_Unwind_Context* context, int index); +typedef uintptr_t GetCFAFn(_Unwind_Context* context); extern "C" SANITIZER_INTERFACE_ATTRIBUTE _Unwind_Reason_Code __hwasan_personality_wrapper(int version, _Unwind_Action actions, @@ -56,6 +56,8 @@ __hwasan_personality_wrapper(int version, _Unwind_Action actions, uptr fp = get_gr(context, 6); // rbp #elif defined(__aarch64__) uptr fp = get_gr(context, 29); // x29 +#elif SANITIZER_RISCV64 + uptr fp = get_gr(context, 8); // x8 #else #error Unsupported architecture #endif diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_flags.inc b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_flags.inc index 18ea47f981b..4a226ee2ab8 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_flags.inc +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_flags.inc @@ -39,7 +39,7 @@ HWASAN_FLAG( HWASAN_FLAG(bool, free_checks_tail_magic, 1, "If set, free() will check the magic values " - "to the right of the allocated object " + "after the allocated object " "if the allocation size is not a divident of the granule size") HWASAN_FLAG( int, max_free_fill_size, 0, diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp index e299a7e862e..d1696f8aa79 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_fuchsia.cpp @@ -15,6 +15,9 @@ #include "sanitizer_common/sanitizer_fuchsia.h" #if SANITIZER_FUCHSIA +#include +#include + #include "hwasan.h" #include "hwasan_interface_internal.h" #include "hwasan_report.h" @@ -130,7 +133,7 @@ static void ThreadCreateHook(void *hook, bool aborted) { static void ThreadStartHook(void *hook, thrd_t self) { Thread *thread = static_cast(hook); FinishThreadInitialization(thread); - thread->InitRandomState(); + thread->EnsureRandomStateInited(); } // This is the function that sets up the stack ring buffer and enables us to use @@ -180,12 +183,33 @@ void HwasanTSDThreadInit() {} // function is unneeded. void InstallAtExitHandler() {} -// TODO(fxbug.dev/81499): Once we finalize the tagged pointer ABI in zircon, we should come back -// here and implement the appropriate check that TBI is enabled. -void InitializeOsSupport() {} +void HwasanInstallAtForkHandler() {} + +void InstallAtExitCheckLeaks() {} + +void InitializeOsSupport() { +#ifdef __aarch64__ + uint32_t features = 0; + CHECK_EQ(zx_system_get_features(ZX_FEATURE_KIND_ADDRESS_TAGGING, &features), + ZX_OK); + if (!(features & ZX_ARM64_FEATURE_ADDRESS_TAGGING_TBI) && + flags()->fail_without_syscall_abi) { + Printf( + "FATAL: HWAddressSanitizer requires " + "ZX_ARM64_FEATURE_ADDRESS_TAGGING_TBI.\n"); + Die(); + } +#endif +} } // namespace __hwasan +namespace __lsan { + +bool UseExitcodeOnLeak() { return __hwasan::flags()->halt_on_error; } + +} // namespace __lsan + extern "C" { void *__sanitizer_before_thread_create_hook(thrd_t thread, bool detached, @@ -208,6 +232,10 @@ void __sanitizer_thread_exit_hook(void *hook, thrd_t self) { __hwasan::ThreadExitHook(hook, self); } +void __sanitizer_module_loaded(const struct dl_phdr_info *info, size_t) { + __hwasan_library_loaded(info->dlpi_addr, info->dlpi_phdr, info->dlpi_phnum); +} + } // extern "C" #endif // SANITIZER_FUCHSIA diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_interceptors.cpp index 68f8adec077..05bf3f29eca 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_interceptors.cpp +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_interceptors.cpp @@ -47,17 +47,22 @@ INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*), return res; } +INTERCEPTOR(int, pthread_join, void *t, void **arg) { + return REAL(pthread_join)(t, arg); +} + +DEFINE_REAL_PTHREAD_FUNCTIONS + DEFINE_REAL(int, vfork) DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork) -#endif // HWASAN_WITH_INTERCEPTORS -#if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__) // Get and/or change the set of blocked signals. extern "C" int sigprocmask(int __how, const __hw_sigset_t *__restrict __set, __hw_sigset_t *__restrict __oset); #define SIG_BLOCK 0 #define SIG_SETMASK 2 extern "C" int __sigjmp_save(__hw_sigjmp_buf env, int savemask) { + env[0].__magic = kHwJmpBufMagic; env[0].__mask_was_saved = (savemask && sigprocmask(SIG_BLOCK, (__hw_sigset_t *)0, &env[0].__saved_mask) == 0); @@ -66,8 +71,16 @@ extern "C" int __sigjmp_save(__hw_sigjmp_buf env, int savemask) { static void __attribute__((always_inline)) InternalLongjmp(__hw_register_buf env, int retval) { +# if defined(__aarch64__) + constexpr size_t kSpIndex = 13; +# elif defined(__x86_64__) + constexpr size_t kSpIndex = 6; +# elif SANITIZER_RISCV64 + constexpr size_t kSpIndex = 13; +# endif + // Clear all memory tags on the stack between here and where we're going. - unsigned long long stack_pointer = env[13]; + unsigned long long stack_pointer = env[kSpIndex]; // The stack pointer should never be tagged, so we don't need to clear the // tag for this function call. __hwasan_handle_longjmp((void *)stack_pointer); @@ -78,6 +91,7 @@ InternalLongjmp(__hw_register_buf env, int retval) { // Must implement this ourselves, since we don't know the order of registers // in different libc implementations and many implementations mangle the // stack pointer so we can't use it without knowing the demangling scheme. +# if defined(__aarch64__) register long int retval_tmp asm("x1") = retval; register void *env_address asm("x0") = &env[0]; asm volatile("ldp x19, x20, [%0, #0<<3];" @@ -100,9 +114,79 @@ InternalLongjmp(__hw_register_buf env, int retval) { "br x30;" : "+r"(env_address) : "r"(retval_tmp)); +# elif defined(__x86_64__) + register long int retval_tmp asm("%rsi") = retval; + register void *env_address asm("%rdi") = &env[0]; + asm volatile( + // Restore registers. + "mov (0*8)(%0),%%rbx;" + "mov (1*8)(%0),%%rbp;" + "mov (2*8)(%0),%%r12;" + "mov (3*8)(%0),%%r13;" + "mov (4*8)(%0),%%r14;" + "mov (5*8)(%0),%%r15;" + "mov (6*8)(%0),%%rsp;" + "mov (7*8)(%0),%%rdx;" + // Return 1 if retval is 0. + "mov $1,%%rax;" + "test %1,%1;" + "cmovnz %1,%%rax;" + "jmp *%%rdx;" ::"r"(env_address), + "r"(retval_tmp)); +# elif SANITIZER_RISCV64 + register long int retval_tmp asm("x11") = retval; + register void *env_address asm("x10") = &env[0]; + asm volatile( + "ld ra, 0<<3(%0);" + "ld s0, 1<<3(%0);" + "ld s1, 2<<3(%0);" + "ld s2, 3<<3(%0);" + "ld s3, 4<<3(%0);" + "ld s4, 5<<3(%0);" + "ld s5, 6<<3(%0);" + "ld s6, 7<<3(%0);" + "ld s7, 8<<3(%0);" + "ld s8, 9<<3(%0);" + "ld s9, 10<<3(%0);" + "ld s10, 11<<3(%0);" + "ld s11, 12<<3(%0);" +# if __riscv_float_abi_double + "fld fs0, 14<<3(%0);" + "fld fs1, 15<<3(%0);" + "fld fs2, 16<<3(%0);" + "fld fs3, 17<<3(%0);" + "fld fs4, 18<<3(%0);" + "fld fs5, 19<<3(%0);" + "fld fs6, 20<<3(%0);" + "fld fs7, 21<<3(%0);" + "fld fs8, 22<<3(%0);" + "fld fs9, 23<<3(%0);" + "fld fs10, 24<<3(%0);" + "fld fs11, 25<<3(%0);" +# elif __riscv_float_abi_soft +# else +# error "Unsupported case" +# endif + "ld a4, 13<<3(%0);" + "mv sp, a4;" + // Return the value requested to return through arguments. + // This should be in x11 given what we requested above. + "seqz a0, %1;" + "add a0, a0, %1;" + "ret;" + : "+r"(env_address) + : "r"(retval_tmp)); +# endif } INTERCEPTOR(void, siglongjmp, __hw_sigjmp_buf env, int val) { + if (env[0].__magic != kHwJmpBufMagic) { + Printf( + "WARNING: Unexpected bad jmp_buf. Either setjmp was not called or " + "there is a bug in HWASan.\n"); + return REAL(siglongjmp)(env, val); + } + if (env[0].__mask_was_saved) // Restore the saved signal mask. (void)sigprocmask(SIG_SETMASK, &env[0].__saved_mask, @@ -114,36 +198,32 @@ INTERCEPTOR(void, siglongjmp, __hw_sigjmp_buf env, int val) { // _setjmp on start_thread. Hence we have to intercept the longjmp on // pthread_exit so the __hw_jmp_buf order matches. INTERCEPTOR(void, __libc_longjmp, __hw_jmp_buf env, int val) { + if (env[0].__magic != kHwJmpBufMagic) + return REAL(__libc_longjmp)(env, val); InternalLongjmp(env[0].__jmpbuf, val); } INTERCEPTOR(void, longjmp, __hw_jmp_buf env, int val) { + if (env[0].__magic != kHwJmpBufMagic) { + Printf( + "WARNING: Unexpected bad jmp_buf. Either setjmp was not called or " + "there is a bug in HWASan.\n"); + return REAL(longjmp)(env, val); + } InternalLongjmp(env[0].__jmpbuf, val); } #undef SIG_BLOCK #undef SIG_SETMASK -#endif // HWASAN_WITH_INTERCEPTORS && __aarch64__ - -static void BeforeFork() { - StackDepotLockAll(); -} - -static void AfterFork() { - StackDepotUnlockAll(); -} - -INTERCEPTOR(int, fork, void) { - ENSURE_HWASAN_INITED(); - BeforeFork(); - int pid = REAL(fork)(); - AfterFork(); - return pid; -} +# endif // HWASAN_WITH_INTERCEPTORS namespace __hwasan { int OnExit() { + if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks && + __lsan::HasReportedLeaks()) { + return common_flags()->exitcode; + } // FIXME: ask frontend whether we need to return failure. return 0; } @@ -156,14 +236,16 @@ void InitializeInterceptors() { static int inited = 0; CHECK_EQ(inited, 0); - INTERCEPT_FUNCTION(fork); - #if HWASAN_WITH_INTERCEPTORS #if defined(__linux__) + INTERCEPT_FUNCTION(__libc_longjmp); + INTERCEPT_FUNCTION(longjmp); + INTERCEPT_FUNCTION(siglongjmp); INTERCEPT_FUNCTION(vfork); #endif // __linux__ INTERCEPT_FUNCTION(pthread_create); -#endif + INTERCEPT_FUNCTION(pthread_join); +# endif inited = 1; } diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_interface_internal.h b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_interface_internal.h index 25c0f94fe51..d1ecbb592a2 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_interface_internal.h +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_interface_internal.h @@ -168,53 +168,13 @@ void __hwasan_thread_exit(); SANITIZER_INTERFACE_ATTRIBUTE void __hwasan_print_memory_usage(); +// The compiler will generate this when +// `-hwasan-record-stack-history-with-calls` is added as a flag, which will add +// frame record information to the stack ring buffer. This is an alternative to +// the compiler emitting instructions in the prologue for doing the same thing +// by accessing the ring buffer directly. SANITIZER_INTERFACE_ATTRIBUTE -int __sanitizer_posix_memalign(void **memptr, uptr alignment, uptr size); - -SANITIZER_INTERFACE_ATTRIBUTE -void * __sanitizer_memalign(uptr alignment, uptr size); - -SANITIZER_INTERFACE_ATTRIBUTE -void * __sanitizer_aligned_alloc(uptr alignment, uptr size); - -SANITIZER_INTERFACE_ATTRIBUTE -void * __sanitizer___libc_memalign(uptr alignment, uptr size); - -SANITIZER_INTERFACE_ATTRIBUTE -void * __sanitizer_valloc(uptr size); - -SANITIZER_INTERFACE_ATTRIBUTE -void * __sanitizer_pvalloc(uptr size); - -SANITIZER_INTERFACE_ATTRIBUTE -void __sanitizer_free(void *ptr); - -SANITIZER_INTERFACE_ATTRIBUTE -void __sanitizer_cfree(void *ptr); - -SANITIZER_INTERFACE_ATTRIBUTE -uptr __sanitizer_malloc_usable_size(const void *ptr); - -SANITIZER_INTERFACE_ATTRIBUTE -__hwasan::__sanitizer_struct_mallinfo __sanitizer_mallinfo(); - -SANITIZER_INTERFACE_ATTRIBUTE -int __sanitizer_mallopt(int cmd, int value); - -SANITIZER_INTERFACE_ATTRIBUTE -void __sanitizer_malloc_stats(void); - -SANITIZER_INTERFACE_ATTRIBUTE -void * __sanitizer_calloc(uptr nmemb, uptr size); - -SANITIZER_INTERFACE_ATTRIBUTE -void * __sanitizer_realloc(void *ptr, uptr size); - -SANITIZER_INTERFACE_ATTRIBUTE -void * __sanitizer_reallocarray(void *ptr, uptr nmemb, uptr size); - -SANITIZER_INTERFACE_ATTRIBUTE -void * __sanitizer_malloc(uptr size); +void __hwasan_add_frame_record(u64 frame_record_info); SANITIZER_INTERFACE_ATTRIBUTE void *__hwasan_memcpy(void *dst, const void *src, uptr size); diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_linux.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_linux.cpp index e22723529f4..d3e4b5390e8 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_linux.cpp +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_linux.cpp @@ -15,30 +15,30 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD -#include "hwasan.h" -#include "hwasan_dynamic_shadow.h" -#include "hwasan_interface_internal.h" -#include "hwasan_mapping.h" -#include "hwasan_report.h" -#include "hwasan_thread.h" -#include "hwasan_thread_list.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_procmaps.h" +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include "hwasan.h" +# include "hwasan_dynamic_shadow.h" +# include "hwasan_interface_internal.h" +# include "hwasan_mapping.h" +# include "hwasan_report.h" +# include "hwasan_thread.h" +# include "hwasan_thread_list.h" +# include "sanitizer_common/sanitizer_common.h" +# include "sanitizer_common/sanitizer_procmaps.h" +# include "sanitizer_common/sanitizer_stackdepot.h" // Configurations of HWASAN_WITH_INTERCEPTORS and SANITIZER_ANDROID. // @@ -50,10 +50,10 @@ // Tested with check-hwasan on x86_64-linux. // HWASAN_WITH_INTERCEPTORS=ON, SANITIZER_ANDROID=ON // Tested with check-hwasan on aarch64-linux-android. -#if !SANITIZER_ANDROID +# if !SANITIZER_ANDROID SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL uptr __hwasan_tls; -#endif +# endif namespace __hwasan { @@ -110,15 +110,84 @@ static void InitializeShadowBaseAddress(uptr shadow_size_bytes) { FindDynamicShadowStart(shadow_size_bytes); } +static void MaybeDieIfNoTaggingAbi(const char *message) { + if (!flags()->fail_without_syscall_abi) + return; + Printf("FATAL: %s\n", message); + Die(); +} + +# define PR_SET_TAGGED_ADDR_CTRL 55 +# define PR_GET_TAGGED_ADDR_CTRL 56 +# define PR_TAGGED_ADDR_ENABLE (1UL << 0) +# define ARCH_GET_UNTAG_MASK 0x4001 +# define ARCH_ENABLE_TAGGED_ADDR 0x4002 +# define ARCH_GET_MAX_TAG_BITS 0x4003 + +static bool CanUseTaggingAbi() { +# if defined(__x86_64__) + unsigned long num_bits = 0; + // Check for x86 LAM support. This API is based on a currently unsubmitted + // patch to the Linux kernel (as of August 2022) and is thus subject to + // change. The patch is here: + // https://lore.kernel.org/all/20220815041803.17954-1-kirill.shutemov@linux.intel.com/ + // + // arch_prctl(ARCH_GET_MAX_TAG_BITS, &bits) returns the maximum number of tag + // bits the user can request, or zero if LAM is not supported by the hardware. + if (internal_iserror(internal_arch_prctl(ARCH_GET_MAX_TAG_BITS, + reinterpret_cast(&num_bits)))) + return false; + // The platform must provide enough bits for HWASan tags. + if (num_bits < kTagBits) + return false; + return true; +# else + // Check for ARM TBI support. + return !internal_iserror(internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0)); +# endif // __x86_64__ +} + +static bool EnableTaggingAbi() { +# if defined(__x86_64__) + // Enable x86 LAM tagging for the process. + // + // arch_prctl(ARCH_ENABLE_TAGGED_ADDR, bits) enables tagging if the number of + // tag bits requested by the user does not exceed that provided by the system. + // arch_prctl(ARCH_GET_UNTAG_MASK, &mask) returns the mask of significant + // address bits. It is ~0ULL if either LAM is disabled for the process or LAM + // is not supported by the hardware. + if (internal_iserror(internal_arch_prctl(ARCH_ENABLE_TAGGED_ADDR, kTagBits))) + return false; + unsigned long mask = 0; + // Make sure the tag bits are where we expect them to be. + if (internal_iserror(internal_arch_prctl(ARCH_GET_UNTAG_MASK, + reinterpret_cast(&mask)))) + return false; + // @mask has ones for non-tag bits, whereas @kAddressTagMask has ones for tag + // bits. Therefore these masks must not overlap. + if (mask & kAddressTagMask) + return false; + return true; +# else + // Enable ARM TBI tagging for the process. If for some reason tagging is not + // supported, prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE) returns + // -EINVAL. + if (internal_iserror(internal_prctl(PR_SET_TAGGED_ADDR_CTRL, + PR_TAGGED_ADDR_ENABLE, 0, 0, 0))) + return false; + // Ensure that TBI is enabled. + if (internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0) != + PR_TAGGED_ADDR_ENABLE) + return false; + return true; +# endif // __x86_64__ +} + void InitializeOsSupport() { -#define PR_SET_TAGGED_ADDR_CTRL 55 -#define PR_GET_TAGGED_ADDR_CTRL 56 -#define PR_TAGGED_ADDR_ENABLE (1UL << 0) // Check we're running on a kernel that can use the tagged address ABI. - int local_errno = 0; - if (internal_iserror(internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0), - &local_errno) && - local_errno == EINVAL) { + bool has_abi = CanUseTaggingAbi(); + + if (!has_abi) { # if SANITIZER_ANDROID || defined(HWASAN_ALIASING_MODE) // Some older Android kernels have the tagged pointer ABI on // unconditionally, and hence don't have the tagged-addr prctl while still @@ -127,46 +196,22 @@ void InitializeOsSupport() { // case. return; # else - if (flags()->fail_without_syscall_abi) { - Printf( - "FATAL: " - "HWAddressSanitizer requires a kernel with tagged address ABI.\n"); - Die(); - } + MaybeDieIfNoTaggingAbi( + "HWAddressSanitizer requires a kernel with tagged address ABI."); # endif } - // Turn on the tagged address ABI. - if ((internal_iserror(internal_prctl(PR_SET_TAGGED_ADDR_CTRL, - PR_TAGGED_ADDR_ENABLE, 0, 0, 0)) || - !internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0))) { -# if defined(__x86_64__) && !defined(HWASAN_ALIASING_MODE) - // Try the new prctl API for Intel LAM. The API is based on a currently - // unsubmitted patch to the Linux kernel (as of May 2021) and is thus - // subject to change. Patch is here: - // https://lore.kernel.org/linux-mm/20210205151631.43511-12-kirill.shutemov@linux.intel.com/ - int tag_bits = kTagBits; - int tag_shift = kAddressTagShift; - if (!internal_iserror( - internal_prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, - reinterpret_cast(&tag_bits), - reinterpret_cast(&tag_shift), 0))) { - CHECK_EQ(tag_bits, kTagBits); - CHECK_EQ(tag_shift, kAddressTagShift); - return; - } -# endif // defined(__x86_64__) && !defined(HWASAN_ALIASING_MODE) - if (flags()->fail_without_syscall_abi) { - Printf( - "FATAL: HWAddressSanitizer failed to enable tagged address syscall " - "ABI.\nSuggest check `sysctl abi.tagged_addr_disabled` " - "configuration.\n"); - Die(); - } - } -#undef PR_SET_TAGGED_ADDR_CTRL -#undef PR_GET_TAGGED_ADDR_CTRL -#undef PR_TAGGED_ADDR_ENABLE + if (EnableTaggingAbi()) + return; + +# if SANITIZER_ANDROID + MaybeDieIfNoTaggingAbi( + "HWAddressSanitizer failed to enable tagged address syscall ABI.\n" + "Check the `sysctl abi.tagged_addr_disabled` configuration."); +# else + MaybeDieIfNoTaggingAbi( + "HWAddressSanitizer failed to enable tagged address syscall ABI.\n"); +# endif } bool InitShadow() { @@ -241,17 +286,16 @@ bool MemIsApp(uptr p) { CHECK(GetTagFromPointer(p) == 0); # endif - return p >= kHighMemStart || (p >= kLowMemStart && p <= kLowMemEnd); + return (p >= kHighMemStart && p <= kHighMemEnd) || + (p >= kLowMemStart && p <= kLowMemEnd); } -void InstallAtExitHandler() { - atexit(HwasanAtExit); -} +void InstallAtExitHandler() { atexit(HwasanAtExit); } // ---------------------- TSD ---------------- {{{1 extern "C" void __hwasan_thread_enter() { - hwasanThreadList().CreateCurrentThread()->InitRandomState(); + hwasanThreadList().CreateCurrentThread()->EnsureRandomStateInited(); } extern "C" void __hwasan_thread_exit() { @@ -262,7 +306,7 @@ extern "C" void __hwasan_thread_exit() { hwasanThreadList().ReleaseThread(t); } -#if HWASAN_WITH_INTERCEPTORS +# if HWASAN_WITH_INTERCEPTORS static pthread_key_t tsd_key; static bool tsd_key_inited = false; @@ -286,22 +330,18 @@ void HwasanTSDInit() { tsd_key_inited = true; CHECK_EQ(0, pthread_key_create(&tsd_key, HwasanTSDDtor)); } -#else +# else void HwasanTSDInit() {} void HwasanTSDThreadInit() {} -#endif +# endif -#if SANITIZER_ANDROID -uptr *GetCurrentThreadLongPtr() { - return (uptr *)get_android_tls_ptr(); -} -#else -uptr *GetCurrentThreadLongPtr() { - return &__hwasan_tls; -} -#endif +# if SANITIZER_ANDROID +uptr *GetCurrentThreadLongPtr() { return (uptr *)get_android_tls_ptr(); } +# else +uptr *GetCurrentThreadLongPtr() { return &__hwasan_tls; } +# endif -#if SANITIZER_ANDROID +# if SANITIZER_ANDROID void AndroidTestTlsSlot() { uptr kMagicValue = 0x010203040A0B0C0D; uptr *tls_ptr = GetCurrentThreadLongPtr(); @@ -316,9 +356,9 @@ void AndroidTestTlsSlot() { } *tls_ptr = old_value; } -#else +# else void AndroidTestTlsSlot() {} -#endif +# endif static AccessInfo GetAccessInfo(siginfo_t *info, ucontext_t *uc) { // Access type is passed in a platform dependent way (see below) and encoded @@ -326,32 +366,32 @@ static AccessInfo GetAccessInfo(siginfo_t *info, ucontext_t *uc) { // recoverable. Valid values of Y are 0 to 4, which are interpreted as // log2(access_size), and 0xF, which means that access size is passed via // platform dependent register (see below). -#if defined(__aarch64__) +# if defined(__aarch64__) // Access type is encoded in BRK immediate as 0x900 + 0xXY. For Y == 0xF, // access size is stored in X1 register. Access address is always in X0 // register. uptr pc = (uptr)info->si_addr; const unsigned code = ((*(u32 *)pc) >> 5) & 0xffff; if ((code & 0xff00) != 0x900) - return AccessInfo{}; // Not ours. + return AccessInfo{}; // Not ours. const bool is_store = code & 0x10; const bool recover = code & 0x20; const uptr addr = uc->uc_mcontext.regs[0]; const unsigned size_log = code & 0xf; if (size_log > 4 && size_log != 0xf) - return AccessInfo{}; // Not ours. + return AccessInfo{}; // Not ours. const uptr size = size_log == 0xf ? uc->uc_mcontext.regs[1] : 1U << size_log; -#elif defined(__x86_64__) +# elif defined(__x86_64__) // Access type is encoded in the instruction following INT3 as // NOP DWORD ptr [EAX + 0x40 + 0xXY]. For Y == 0xF, access size is stored in // RSI register. Access address is always in RDI register. uptr pc = (uptr)uc->uc_mcontext.gregs[REG_RIP]; - uint8_t *nop = (uint8_t*)pc; - if (*nop != 0x0f || *(nop + 1) != 0x1f || *(nop + 2) != 0x40 || + uint8_t *nop = (uint8_t *)pc; + if (*nop != 0x0f || *(nop + 1) != 0x1f || *(nop + 2) != 0x40 || *(nop + 3) < 0x40) - return AccessInfo{}; // Not ours. + return AccessInfo{}; // Not ours. const unsigned code = *(nop + 3); const bool is_store = code & 0x10; @@ -359,13 +399,54 @@ static AccessInfo GetAccessInfo(siginfo_t *info, ucontext_t *uc) { const uptr addr = uc->uc_mcontext.gregs[REG_RDI]; const unsigned size_log = code & 0xf; if (size_log > 4 && size_log != 0xf) - return AccessInfo{}; // Not ours. + return AccessInfo{}; // Not ours. const uptr size = size_log == 0xf ? uc->uc_mcontext.gregs[REG_RSI] : 1U << size_log; -#else -# error Unsupported architecture -#endif +# elif SANITIZER_RISCV64 + // Access type is encoded in the instruction following EBREAK as + // ADDI x0, x0, [0x40 + 0xXY]. For Y == 0xF, access size is stored in + // X11 register. Access address is always in X10 register. + uptr pc = (uptr)uc->uc_mcontext.__gregs[REG_PC]; + uint8_t byte1 = *((u8 *)(pc + 0)); + uint8_t byte2 = *((u8 *)(pc + 1)); + uint8_t byte3 = *((u8 *)(pc + 2)); + uint8_t byte4 = *((u8 *)(pc + 3)); + uint32_t ebreak = (byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24)); + bool isFaultShort = false; + bool isEbreak = (ebreak == 0x100073); + bool isShortEbreak = false; +# if defined(__riscv_compressed) + isFaultShort = ((ebreak & 0x3) != 0x3); + isShortEbreak = ((ebreak & 0xffff) == 0x9002); +# endif + // faulted insn is not ebreak, not our case + if (!(isEbreak || isShortEbreak)) + return AccessInfo{}; + // advance pc to point after ebreak and reconstruct addi instruction + pc += isFaultShort ? 2 : 4; + byte1 = *((u8 *)(pc + 0)); + byte2 = *((u8 *)(pc + 1)); + byte3 = *((u8 *)(pc + 2)); + byte4 = *((u8 *)(pc + 3)); + // reconstruct instruction + uint32_t instr = (byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24)); + // check if this is really 32 bit instruction + // code is encoded in top 12 bits, since instruction is supposed to be with + // imm + const unsigned code = (instr >> 20) & 0xffff; + const uptr addr = uc->uc_mcontext.__gregs[10]; + const bool is_store = code & 0x10; + const bool recover = code & 0x20; + const unsigned size_log = code & 0xf; + if (size_log > 4 && size_log != 0xf) + return AccessInfo{}; // Not our case + const uptr size = + size_log == 0xf ? uc->uc_mcontext.__gregs[11] : 1U << size_log; + +# else +# error Unsupported architecture +# endif return AccessInfo{addr, size, is_store, !is_store, recover}; } @@ -378,12 +459,25 @@ static bool HwasanOnSIGTRAP(int signo, siginfo_t *info, ucontext_t *uc) { SignalContext sig{info, uc}; HandleTagMismatch(ai, StackTrace::GetNextInstructionPc(sig.pc), sig.bp, uc); -#if defined(__aarch64__) +# if defined(__aarch64__) uc->uc_mcontext.pc += 4; -#elif defined(__x86_64__) -#else -# error Unsupported architecture -#endif +# elif defined(__x86_64__) +# elif SANITIZER_RISCV64 + // pc points to EBREAK which is 2 bytes long + uint8_t *exception_source = (uint8_t *)(uc->uc_mcontext.__gregs[REG_PC]); + uint8_t byte1 = (uint8_t)(*(exception_source + 0)); + uint8_t byte2 = (uint8_t)(*(exception_source + 1)); + uint8_t byte3 = (uint8_t)(*(exception_source + 2)); + uint8_t byte4 = (uint8_t)(*(exception_source + 3)); + uint32_t faulted = (byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24)); + bool isFaultShort = false; +# if defined(__riscv_compressed) + isFaultShort = ((faulted & 0x3) != 0x3); +# endif + uc->uc_mcontext.__gregs[REG_PC] += isFaultShort ? 2 : 4; +# else +# error Unsupported architecture +# endif return true; } @@ -396,7 +490,7 @@ static void OnStackUnwind(const SignalContext &sig, const void *, void HwasanOnDeadlySignal(int signo, void *info, void *context) { // Probably a tag mismatch. if (signo == SIGTRAP) - if (HwasanOnSIGTRAP(signo, (siginfo_t *)info, (ucontext_t*)context)) + if (HwasanOnSIGTRAP(signo, (siginfo_t *)info, (ucontext_t *)context)) return; HandleDeadlySignal(info, context, GetTid(), &OnStackUnwind, nullptr); @@ -435,6 +529,29 @@ uptr TagMemoryAligned(uptr p, uptr size, tag_t tag) { return AddTagToPointer(p, tag); } -} // namespace __hwasan +void HwasanInstallAtForkHandler() { + auto before = []() { + HwasanAllocatorLock(); + StackDepotLockAll(); + }; + auto after = []() { + StackDepotUnlockAll(); + HwasanAllocatorUnlock(); + }; + pthread_atfork(before, after, after); +} + +void InstallAtExitCheckLeaks() { + if (CAN_SANITIZE_LEAKS) { + if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) { + if (flags()->halt_on_error) + Atexit(__lsan::DoLeakCheck); + else + Atexit(__lsan::DoRecoverableLeakCheckVoid); + } + } +} + +} // namespace __hwasan -#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD +#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_memintrinsics.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_memintrinsics.cpp index fab017aae60..ea7f5ce40b0 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_memintrinsics.cpp +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_memintrinsics.cpp @@ -40,5 +40,5 @@ void *__hwasan_memmove(void *to, const void *from, uptr size) { reinterpret_cast(to), size); CheckAddressSized( reinterpret_cast(from), size); - return memmove(UntagPtr(to), UntagPtr(from), size); + return memmove(to, from, size); } diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_new_delete.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_new_delete.cpp index 4e057a651e1..495046a754f 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_new_delete.cpp +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_new_delete.cpp @@ -22,21 +22,23 @@ #if HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE // TODO(alekseys): throw std::bad_alloc instead of dying on OOM. -#define OPERATOR_NEW_BODY(nothrow) \ - GET_MALLOC_STACK_TRACE; \ - void *res = hwasan_malloc(size, &stack);\ - if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\ - return res -#define OPERATOR_NEW_ALIGN_BODY(nothrow) \ - GET_MALLOC_STACK_TRACE; \ - void *res = hwasan_aligned_alloc(static_cast(align), size, &stack); \ - if (!nothrow && UNLIKELY(!res)) \ - ReportOutOfMemory(size, &stack); \ - return res - -#define OPERATOR_DELETE_BODY \ - GET_MALLOC_STACK_TRACE; \ - if (ptr) hwasan_free(ptr, &stack) +# define OPERATOR_NEW_BODY(nothrow) \ + GET_MALLOC_STACK_TRACE; \ + void *res = hwasan_malloc(size, &stack); \ + if (!nothrow && UNLIKELY(!res)) \ + ReportOutOfMemory(size, &stack); \ + return res +# define OPERATOR_NEW_ALIGN_BODY(nothrow) \ + GET_MALLOC_STACK_TRACE; \ + void *res = hwasan_memalign(static_cast(align), size, &stack); \ + if (!nothrow && UNLIKELY(!res)) \ + ReportOutOfMemory(size, &stack); \ + return res + +# define OPERATOR_DELETE_BODY \ + GET_MALLOC_STACK_TRACE; \ + if (ptr) \ + hwasan_free(ptr, &stack) #elif defined(__ANDROID__) @@ -44,8 +46,8 @@ // since we previously released a runtime that intercepted these functions, // removing the interceptors would break ABI. Therefore we simply forward to // malloc and free. -#define OPERATOR_NEW_BODY(nothrow) return malloc(size) -#define OPERATOR_DELETE_BODY free(ptr) +# define OPERATOR_NEW_BODY(nothrow) return malloc(size) +# define OPERATOR_DELETE_BODY free(ptr) #endif @@ -55,26 +57,27 @@ using namespace __hwasan; // Fake std::nothrow_t to avoid including . namespace std { - struct nothrow_t {}; +struct nothrow_t {}; } // namespace std - - -INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE -void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } -INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE -void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } -INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE -void *operator new(size_t size, std::nothrow_t const&) { +INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(size_t size) { + OPERATOR_NEW_BODY(false /*nothrow*/); +} +INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[]( + size_t size) { + OPERATOR_NEW_BODY(false /*nothrow*/); +} +INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new( + size_t size, std::nothrow_t const &) { OPERATOR_NEW_BODY(true /*nothrow*/); } -INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE -void *operator new[](size_t size, std::nothrow_t const&) { +INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[]( + size_t size, std::nothrow_t const &) { OPERATOR_NEW_BODY(true /*nothrow*/); } -INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(void *ptr) - NOEXCEPT { +INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete( + void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[]( diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_poisoning.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_poisoning.cpp index 5aafdb1884b..a4e5935754a 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_poisoning.cpp +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_poisoning.cpp @@ -26,3 +26,11 @@ uptr TagMemory(uptr p, uptr size, tag_t tag) { } } // namespace __hwasan + +// --- Implementation of LSan-specific functions --- {{{1 +namespace __lsan { +bool WordIsPoisoned(uptr addr) { + // Fixme: implement actual tag checking. + return false; +} +} // namespace __lsan diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_preinit.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_preinit.cpp new file mode 100644 index 00000000000..8c9c95f413b --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_preinit.cpp @@ -0,0 +1,23 @@ +//===-- hwasan_preinit.cpp ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of HWAddressSanitizer, an address sanity checker. +// +// Call __hwasan_init at the very early stage of process startup. +//===----------------------------------------------------------------------===// +#include "hwasan_interface_internal.h" +#include "sanitizer_common/sanitizer_internal_defs.h" + +#if SANITIZER_CAN_USE_PREINIT_ARRAY +// The symbol is called __local_hwasan_preinit, because it's not intended to +// be exported. +// This code linked into the main executable when -fsanitize=hwaddress is in +// the link flags. It can only use exported interface functions. +__attribute__((section(".preinit_array"), used)) static void ( + *__local_hwasan_preinit)(void) = __hwasan_init; +#endif diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_report.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_report.cpp index 44047c9fdaf..31e190a8ebb 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_report.cpp +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_report.cpp @@ -37,7 +37,7 @@ namespace __hwasan { class ScopedReport { public: ScopedReport(bool fatal = false) : error_message_(1), fatal(fatal) { - BlockingMutexLock lock(&error_message_lock_); + Lock lock(&error_message_lock_); error_message_ptr_ = fatal ? &error_message_ : nullptr; ++hwasan_report_count; } @@ -45,7 +45,7 @@ class ScopedReport { ~ScopedReport() { void (*report_cb)(const char *); { - BlockingMutexLock lock(&error_message_lock_); + Lock lock(&error_message_lock_); report_cb = error_report_callback_; error_message_ptr_ = nullptr; } @@ -61,7 +61,7 @@ class ScopedReport { } static void MaybeAppendToErrorMessage(const char *msg) { - BlockingMutexLock lock(&error_message_lock_); + Lock lock(&error_message_lock_); if (!error_message_ptr_) return; uptr len = internal_strlen(msg); @@ -72,7 +72,7 @@ class ScopedReport { } static void SetErrorReportCallback(void (*callback)(const char *)) { - BlockingMutexLock lock(&error_message_lock_); + Lock lock(&error_message_lock_); error_report_callback_ = callback; } @@ -82,12 +82,12 @@ class ScopedReport { bool fatal; static InternalMmapVector *error_message_ptr_; - static BlockingMutex error_message_lock_; + static Mutex error_message_lock_; static void (*error_report_callback_)(const char *); }; InternalMmapVector *ScopedReport::error_message_ptr_; -BlockingMutex ScopedReport::error_message_lock_; +Mutex ScopedReport::error_message_lock_; void (*ScopedReport::error_report_callback_)(const char *); // If there is an active ScopedReport, append to its error message. @@ -102,6 +102,15 @@ static StackTrace GetStackTraceFromId(u32 id) { return res; } +static void MaybePrintAndroidHelpUrl() { +#if SANITIZER_ANDROID + Printf( + "Learn more about HWASan reports: " + "https://source.android.com/docs/security/test/memory-safety/" + "hwasan-reports\n"); +#endif +} + // A RAII object that holds a copy of the current thread stack ring buffer. // The actual stack buffer may change while we are iterating over it (for // example, Printf may call syslog() which can itself be built with hwasan). @@ -309,16 +318,16 @@ static void ShowHeapOrGlobalCandidate(uptr untagged_addr, tag_t *candidate, whence = "inside"; } else if (candidate == left) { offset = untagged_addr - chunk.End(); - whence = "to the right of"; + whence = "after"; } else { offset = chunk.Beg() - untagged_addr; - whence = "to the left of"; + whence = "before"; } Printf("%s", d.Error()); Printf("\nCause: heap-buffer-overflow\n"); Printf("%s", d.Default()); Printf("%s", d.Location()); - Printf("%p is located %zd bytes %s %zd-byte region [%p,%p)\n", + Printf("%p is located %zd bytes %s a %zd-byte region [%p,%p)\n", untagged_addr, offset, whence, chunk.UsedSize(), chunk.Beg(), chunk.End()); Printf("%s", d.Allocation()); @@ -340,25 +349,27 @@ static void ShowHeapOrGlobalCandidate(uptr untagged_addr, tag_t *candidate, Printf("%s", d.Location()); if (sym->SymbolizeData(mem, &info) && info.start) { Printf( - "%p is located %zd bytes to the %s of %zd-byte global variable " + "%p is located %zd bytes %s a %zd-byte global variable " "%s [%p,%p) in %s\n", untagged_addr, candidate == left ? untagged_addr - (info.start + info.size) : info.start - untagged_addr, - candidate == left ? "right" : "left", info.size, info.name, + candidate == left ? "after" : "before", info.size, info.name, info.start, info.start + info.size, module_name); } else { uptr size = GetGlobalSizeFromDescriptor(mem); if (size == 0) // We couldn't find the size of the global from the descriptors. - Printf("%p is located to the %s of a global variable in (%s+0x%x)\n", - untagged_addr, candidate == left ? "right" : "left", module_name, - module_address); + Printf( + "%p is located %s a global variable in " + "\n #0 0x%x (%s+0x%x)\n", + untagged_addr, candidate == left ? "after" : "before", mem, + module_name, module_address); else Printf( - "%p is located to the %s of a %zd-byte global variable in " - "(%s+0x%x)\n", - untagged_addr, candidate == left ? "right" : "left", size, + "%p is located %s a %zd-byte global variable in " + "\n #0 0x%x (%s+0x%x)\n", + untagged_addr, candidate == left ? "after" : "before", size, mem, module_name, module_address); } Printf("%s", d.Default()); @@ -372,6 +383,12 @@ void PrintAddressDescription( int num_descriptions_printed = 0; uptr untagged_addr = UntagAddr(tagged_addr); + if (MemIsShadow(untagged_addr)) { + Printf("%s%p is HWAsan shadow memory.\n%s", d.Location(), untagged_addr, + d.Default()); + return; + } + // Print some very basic information about the address, if it's a heap. HwasanChunkView chunk = FindHeapChunkByAddress(untagged_addr); if (uptr beg = chunk.Beg()) { @@ -451,7 +468,7 @@ void PrintAddressDescription( Printf("%s", d.Error()); Printf("\nCause: use-after-free\n"); Printf("%s", d.Location()); - Printf("%p is located %zd bytes inside of %zd-byte region [%p,%p)\n", + Printf("%p is located %zd bytes inside a %zd-byte region [%p,%p)\n", untagged_addr, untagged_addr - UntagAddr(har.tagged_addr), har.requested_size, UntagAddr(har.tagged_addr), UntagAddr(har.tagged_addr) + har.requested_size); @@ -510,7 +527,7 @@ static void PrintTagInfoAroundAddr(tag_t *tag_ptr, uptr num_rows, InternalScopedString s; for (tag_t *row = beg_row; row < end_row; row += row_len) { s.append("%s", row == center_row_beg ? "=>" : " "); - s.append("%p:", row); + s.append("%p:", (void *)ShadowToMem(reinterpret_cast(row))); for (uptr i = 0; i < row_len; i++) { s.append("%s", row + i == tag_ptr ? "[" : " "); print_tag(s, &row[i]); @@ -549,35 +566,65 @@ static void PrintTagsAroundAddr(tag_t *tag_ptr) { "description of short granule tags\n"); } +uptr GetTopPc(StackTrace *stack) { + return stack->size ? StackTrace::GetPreviousInstructionPc(stack->trace[0]) + : 0; +} + void ReportInvalidFree(StackTrace *stack, uptr tagged_addr) { ScopedReport R(flags()->halt_on_error); uptr untagged_addr = UntagAddr(tagged_addr); tag_t ptr_tag = GetTagFromPointer(tagged_addr); - tag_t *tag_ptr = reinterpret_cast(MemToShadow(untagged_addr)); - tag_t mem_tag = *tag_ptr; + tag_t *tag_ptr = nullptr; + tag_t mem_tag = 0; + if (MemIsApp(untagged_addr)) { + tag_ptr = reinterpret_cast(MemToShadow(untagged_addr)); + if (MemIsShadow(reinterpret_cast(tag_ptr))) + mem_tag = *tag_ptr; + else + tag_ptr = nullptr; + } Decorator d; Printf("%s", d.Error()); - uptr pc = stack->size ? stack->trace[0] : 0; + uptr pc = GetTopPc(stack); const char *bug_type = "invalid-free"; - Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type, - untagged_addr, pc); + const Thread *thread = GetCurrentThread(); + if (thread) { + Report("ERROR: %s: %s on address %p at pc %p on thread T%zd\n", + SanitizerToolName, bug_type, untagged_addr, pc, thread->unique_id()); + } else { + Report("ERROR: %s: %s on address %p at pc %p on unknown thread\n", + SanitizerToolName, bug_type, untagged_addr, pc); + } Printf("%s", d.Access()); - Printf("tags: %02x/%02x (ptr/mem)\n", ptr_tag, mem_tag); + if (tag_ptr) + Printf("tags: %02x/%02x (ptr/mem)\n", ptr_tag, mem_tag); Printf("%s", d.Default()); stack->Print(); PrintAddressDescription(tagged_addr, 0, nullptr); - PrintTagsAroundAddr(tag_ptr); + if (tag_ptr) + PrintTagsAroundAddr(tag_ptr); + MaybePrintAndroidHelpUrl(); ReportErrorSummary(bug_type, stack); } void ReportTailOverwritten(StackTrace *stack, uptr tagged_addr, uptr orig_size, const u8 *expected) { uptr tail_size = kShadowAlignment - (orig_size % kShadowAlignment); + u8 actual_expected[kShadowAlignment]; + internal_memcpy(actual_expected, expected, tail_size); + tag_t ptr_tag = GetTagFromPointer(tagged_addr); + // Short granule is stashed in the last byte of the magic string. To avoid + // confusion, make the expected magic string contain the short granule tag. + if (orig_size % kShadowAlignment != 0) { + actual_expected[tail_size - 1] = ptr_tag; + } + ScopedReport R(flags()->halt_on_error); Decorator d; uptr untagged_addr = UntagAddr(tagged_addr); @@ -614,17 +661,16 @@ void ReportTailOverwritten(StackTrace *stack, uptr tagged_addr, uptr orig_size, s.append("Expected: "); for (uptr i = 0; i < kShadowAlignment - tail_size; i++) s.append(".. "); - for (uptr i = 0; i < tail_size; i++) - s.append("%02x ", expected[i]); + for (uptr i = 0; i < tail_size; i++) s.append("%02x ", actual_expected[i]); s.append("\n"); s.append(" "); for (uptr i = 0; i < kShadowAlignment - tail_size; i++) s.append(" "); for (uptr i = 0; i < tail_size; i++) - s.append("%s ", expected[i] != tail[i] ? "^^" : " "); + s.append("%s ", actual_expected[i] != tail[i] ? "^^" : " "); s.append("\nThis error occurs when a buffer overflow overwrites memory\n" - "to the right of a heap object, but within the %zd-byte granule, e.g.\n" + "after a heap object, but within the %zd-byte granule, e.g.\n" " char *x = new char[20];\n" " x[25] = 42;\n" "%s does not detect such bugs in uninstrumented code at the time of write," @@ -637,6 +683,7 @@ void ReportTailOverwritten(StackTrace *stack, uptr tagged_addr, uptr orig_size, tag_t *tag_ptr = reinterpret_cast(MemToShadow(untagged_addr)); PrintTagsAroundAddr(tag_ptr); + MaybePrintAndroidHelpUrl(); ReportErrorSummary(bug_type, stack); } @@ -647,11 +694,11 @@ void ReportTagMismatch(StackTrace *stack, uptr tagged_addr, uptr access_size, GetCurrentThread()->stack_allocations()); Decorator d; - Printf("%s", d.Error()); uptr untagged_addr = UntagAddr(tagged_addr); // TODO: when possible, try to print heap-use-after-free, etc. const char *bug_type = "tag-mismatch"; - uptr pc = stack->size ? stack->trace[0] : 0; + uptr pc = GetTopPc(stack); + Printf("%s", d.Error()); Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type, untagged_addr, pc); @@ -666,12 +713,33 @@ void ReportTagMismatch(StackTrace *stack, uptr tagged_addr, uptr access_size, tag_t mem_tag = *tag_ptr; Printf("%s", d.Access()); - Printf("%s of size %zu at %p tags: %02x/%02x (ptr/mem) in thread T%zd\n", - is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag, - mem_tag, t->unique_id()); + if (mem_tag && mem_tag < kShadowAlignment) { + tag_t *granule_ptr = reinterpret_cast((untagged_addr + offset) & + ~(kShadowAlignment - 1)); + // If offset is 0, (untagged_addr + offset) is not aligned to granules. + // This is the offset of the leftmost accessed byte within the bad granule. + u8 in_granule_offset = (untagged_addr + offset) & (kShadowAlignment - 1); + tag_t short_tag = granule_ptr[kShadowAlignment - 1]; + // The first mismatch was a short granule that matched the ptr_tag. + if (short_tag == ptr_tag) { + // If the access starts after the end of the short granule, then the first + // bad byte is the first byte of the access; otherwise it is the first + // byte past the end of the short granule + if (mem_tag > in_granule_offset) { + offset += mem_tag - in_granule_offset; + } + } + Printf( + "%s of size %zu at %p tags: %02x/%02x(%02x) (ptr/mem) in thread T%zd\n", + is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag, + mem_tag, short_tag, t->unique_id()); + } else { + Printf("%s of size %zu at %p tags: %02x/%02x (ptr/mem) in thread T%zd\n", + is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag, + mem_tag, t->unique_id()); + } if (offset != 0) - Printf("Invalid access starting at offset [%zu, %zu)\n", offset, - Min(access_size, static_cast(offset) + (1 << kShadowScale))); + Printf("Invalid access starting at offset %zu\n", offset); Printf("%s", d.Default()); stack->Print(); @@ -685,11 +753,12 @@ void ReportTagMismatch(StackTrace *stack, uptr tagged_addr, uptr access_size, if (registers_frame) ReportRegisters(registers_frame, pc); + MaybePrintAndroidHelpUrl(); ReportErrorSummary(bug_type, stack); } // See the frame breakdown defined in __hwasan_tag_mismatch (from -// hwasan_tag_mismatch_aarch64.S). +// hwasan_tag_mismatch_{aarch64,riscv64}.S). void ReportRegisters(uptr *frame, uptr pc) { Printf("Registers where the failure occurred (pc %p):\n", pc); @@ -697,8 +766,13 @@ void ReportRegisters(uptr *frame, uptr pc) { // reduce the amount of logcat error messages printed. Each Printf() will // result in a new logcat line, irrespective of whether a newline is present, // and so we wish to reduce the number of Printf() calls we have to make. +#if defined(__aarch64__) Printf(" x0 %016llx x1 %016llx x2 %016llx x3 %016llx\n", frame[0], frame[1], frame[2], frame[3]); +#elif SANITIZER_RISCV64 + Printf(" sp %016llx x1 %016llx x2 %016llx x3 %016llx\n", + reinterpret_cast(frame) + 256, frame[1], frame[2], frame[3]); +#endif Printf(" x4 %016llx x5 %016llx x6 %016llx x7 %016llx\n", frame[4], frame[5], frame[6], frame[7]); Printf(" x8 %016llx x9 %016llx x10 %016llx x11 %016llx\n", @@ -713,8 +787,14 @@ void ReportRegisters(uptr *frame, uptr pc) { frame[24], frame[25], frame[26], frame[27]); // hwasan_check* reduces the stack pointer by 256, then __hwasan_tag_mismatch // passes it to this function. +#if defined(__aarch64__) Printf(" x28 %016llx x29 %016llx x30 %016llx sp %016llx\n", frame[28], frame[29], frame[30], reinterpret_cast(frame) + 256); +#elif SANITIZER_RISCV64 + Printf(" x28 %016llx x29 %016llx x30 %016llx x31 %016llx\n", frame[28], + frame[29], frame[30], frame[31]); +#else +#endif } } // namespace __hwasan diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_setjmp_aarch64.S b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_setjmp_aarch64.S new file mode 100644 index 00000000000..744748a5101 --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_setjmp_aarch64.S @@ -0,0 +1,101 @@ +//===-- hwasan_setjmp_aarch64.S -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of HWAddressSanitizer. +// +// HWAddressSanitizer runtime. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_asm.h" +#include "builtins/assembly.h" + +#if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__) +#include "sanitizer_common/sanitizer_platform.h" + +// We want to save the context of the calling function. +// That requires +// 1) No modification of the link register by this function. +// 2) No modification of the stack pointer by this function. +// 3) (no modification of any other saved register, but that's not really going +// to occur, and hence isn't as much of a worry). +// +// There's essentially no way to ensure that the compiler will not modify the +// stack pointer when compiling a C function. +// Hence we have to write this function in assembly. + +.section .text +.file "hwasan_setjmp_aarch64.S" + +.global __interceptor_setjmp +ASM_TYPE_FUNCTION(__interceptor_setjmp) +__interceptor_setjmp: + CFI_STARTPROC + BTI_C + mov x1, #0 + b __interceptor_sigsetjmp + CFI_ENDPROC +ASM_SIZE(__interceptor_setjmp) + +#if SANITIZER_ANDROID +// Bionic also defines a function `setjmp` that calls `sigsetjmp` saving the +// current signal. +.global __interceptor_setjmp_bionic +ASM_TYPE_FUNCTION(__interceptor_setjmp_bionic) +__interceptor_setjmp_bionic: + CFI_STARTPROC + BTI_C + mov x1, #1 + b __interceptor_sigsetjmp + CFI_ENDPROC +ASM_SIZE(__interceptor_setjmp_bionic) +#endif + +.global __interceptor_sigsetjmp +ASM_TYPE_FUNCTION(__interceptor_sigsetjmp) +__interceptor_sigsetjmp: + CFI_STARTPROC + BTI_C + stp x19, x20, [x0, #0<<3] + stp x21, x22, [x0, #2<<3] + stp x23, x24, [x0, #4<<3] + stp x25, x26, [x0, #6<<3] + stp x27, x28, [x0, #8<<3] + stp x29, x30, [x0, #10<<3] + stp d8, d9, [x0, #14<<3] + stp d10, d11, [x0, #16<<3] + stp d12, d13, [x0, #18<<3] + stp d14, d15, [x0, #20<<3] + mov x2, sp + str x2, [x0, #13<<3] + // We always have the second argument to __sigjmp_save (savemask) set, since + // the _setjmp function above has set it for us as `false`. + // This function is defined in hwasan_interceptors.cc + b __sigjmp_save + CFI_ENDPROC +ASM_SIZE(__interceptor_sigsetjmp) + + +.macro WEAK_ALIAS first second + .weak \second + .equ \second\(), \first +.endm + +#if SANITIZER_ANDROID +WEAK_ALIAS __interceptor_sigsetjmp, sigsetjmp +WEAK_ALIAS __interceptor_setjmp_bionic, setjmp +#else +WEAK_ALIAS __interceptor_sigsetjmp, __sigsetjmp +#endif + +WEAK_ALIAS __interceptor_setjmp, _setjmp +#endif + +// We do not need executable stack. +NO_EXEC_STACK_DIRECTIVE + +GNU_PROPERTY_BTI_PAC diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_setjmp_riscv64.S b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_setjmp_riscv64.S new file mode 100644 index 00000000000..43f9c3c26b4 --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_setjmp_riscv64.S @@ -0,0 +1,97 @@ +//===-- hwasan_setjmp_riscv64.S -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of HWAddressSanitizer. +// setjmp interceptor for risc-v. +// HWAddressSanitizer runtime. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_asm.h" +#include "builtins/assembly.h" + +#if HWASAN_WITH_INTERCEPTORS && defined(__riscv) && (__riscv_xlen == 64) +#include "sanitizer_common/sanitizer_platform.h" + +// We want to save the context of the calling function. +// That requires +// 1) No modification of the link register by this function. +// 2) No modification of the stack pointer by this function. +// 3) (no modification of any other saved register, but that's not really going +// to occur, and hence isn't as much of a worry). +// +// There's essentially no way to ensure that the compiler will not modify the +// stack pointer when compiling a C function. +// Hence we have to write this function in assembly. + +.section .text +.file "hwasan_setjmp_riscv64.S" + +.global __interceptor_setjmp +ASM_TYPE_FUNCTION(__interceptor_setjmp) +__interceptor_setjmp: + CFI_STARTPROC + addi x11, x0, 0 + tail __interceptor_sigsetjmp + CFI_ENDPROC +ASM_SIZE(__interceptor_setjmp) + +.global __interceptor_sigsetjmp +ASM_TYPE_FUNCTION(__interceptor_sigsetjmp) +__interceptor_sigsetjmp: + CFI_STARTPROC + sd ra, 0<<3(x10) + sd s0, 1<<3(x10) + sd s1, 2<<3(x10) + sd s2, 3<<3(x10) + sd s3, 4<<3(x10) + sd s4, 5<<3(x10) + sd s5, 6<<3(x10) + sd s6, 7<<3(x10) + sd s7, 8<<3(x10) + sd s8, 9<<3(x10) + sd s9, 10<<3(x10) + sd s10, 11<<3(x10) + sd s11, 12<<3(x10) + sd sp, 13<<3(x10) +#if __riscv_float_abi_double + fsd fs0, 14<<3(x10) + fsd fs1, 15<<3(x10) + fsd fs2, 16<<3(x10) + fsd fs3, 17<<3(x10) + fsd fs4, 18<<3(x10) + fsd fs5, 19<<3(x10) + fsd fs6, 20<<3(x10) + fsd fs7, 21<<3(x10) + fsd fs8, 22<<3(x10) + fsd fs9, 23<<3(x10) + fsd fs10, 24<<3(x10) + fsd fs11, 25<<3(x10) +#elif __riscv_float_abi_soft +#else +# error "Unsupported case" +#endif + // We always have the second argument to __sigjmp_save (savemask) set, since + // the _setjmp function above has set it for us as `false`. + // This function is defined in hwasan_interceptors.cc + tail __sigjmp_save + CFI_ENDPROC +ASM_SIZE(__interceptor_sigsetjmp) + + +.macro WEAK_ALIAS first second + .weak \second + .equ \second\(), \first +.endm + +WEAK_ALIAS __interceptor_sigsetjmp, __sigsetjmp + +WEAK_ALIAS __interceptor_setjmp, _setjmp +#endif + +// We do not need executable stack. +NO_EXEC_STACK_DIRECTIVE diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_setjmp_x86_64.S b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_setjmp_x86_64.S new file mode 100644 index 00000000000..7566c1ea0a5 --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_setjmp_x86_64.S @@ -0,0 +1,82 @@ +//===-- hwasan_setjmp_x86_64.S --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// setjmp interceptor for x86_64. +// +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_asm.h" + +#if HWASAN_WITH_INTERCEPTORS && defined(__x86_64__) +#include "sanitizer_common/sanitizer_platform.h" + +// We want to save the context of the calling function. +// That requires +// 1) No modification of the return address by this function. +// 2) No modification of the stack pointer by this function. +// 3) (no modification of any other saved register, but that's not really going +// to occur, and hence isn't as much of a worry). +// +// There's essentially no way to ensure that the compiler will not modify the +// stack pointer when compiling a C function. +// Hence we have to write this function in assembly. +// +// TODO: Handle Intel CET. + +.section .text +.file "hwasan_setjmp_x86_64.S" + +.global __interceptor_setjmp +ASM_TYPE_FUNCTION(__interceptor_setjmp) +__interceptor_setjmp: + CFI_STARTPROC + _CET_ENDBR + xorl %esi, %esi + jmp __interceptor_sigsetjmp + CFI_ENDPROC +ASM_SIZE(__interceptor_setjmp) + +.global __interceptor_sigsetjmp +ASM_TYPE_FUNCTION(__interceptor_sigsetjmp) +__interceptor_sigsetjmp: + CFI_STARTPROC + _CET_ENDBR + + // Save callee save registers. + mov %rbx, (0*8)(%rdi) + mov %rbp, (1*8)(%rdi) + mov %r12, (2*8)(%rdi) + mov %r13, (3*8)(%rdi) + mov %r14, (4*8)(%rdi) + mov %r15, (5*8)(%rdi) + + // Save SP as it was in caller's frame. + lea 8(%rsp), %rdx + mov %rdx, (6*8)(%rdi) + + // Save return address. + mov (%rsp), %rax + mov %rax, (7*8)(%rdi) + + jmp __sigjmp_save + + CFI_ENDPROC +ASM_SIZE(__interceptor_sigsetjmp) + + +.macro WEAK_ALIAS first second + .weak \second + .equ \second\(), \first +.endm + +WEAK_ALIAS __interceptor_sigsetjmp, __sigsetjmp +WEAK_ALIAS __interceptor_setjmp, _setjmp +#endif + +// We do not need executable stack. +NO_EXEC_STACK_DIRECTIVE diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_tag_mismatch_riscv64.S b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_tag_mismatch_riscv64.S new file mode 100644 index 00000000000..487a042405b --- /dev/null +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_tag_mismatch_riscv64.S @@ -0,0 +1,132 @@ +#include "sanitizer_common/sanitizer_asm.h" + +// The content of this file is RISCV64-only: +#if defined(__riscv) && (__riscv_xlen == 64) + +// The responsibility of the HWASan entry point in compiler-rt is to primarily +// readjust the stack from the callee and save the current register values to +// the stack. +// This entry point function should be called from a __hwasan_check_* symbol. +// These are generated during a lowering pass in the backend, and are found in +// RISCVAsmPrinter::EmitHwasanMemaccessSymbols(). Please look there for +// further information. +// The __hwasan_check_* caller of this function should have expanded the stack +// and saved the previous values of x10(arg0), x11(arg1), x1(ra), and x8(fp). +// This function will "consume" these saved values and treats it as part of its +// own stack frame. In this sense, the __hwasan_check_* callee and this function +// "share" a stack frame. This allows us to omit having unwinding information +// (.cfi_*) present in every __hwasan_check_* function, therefore reducing binary size. +// This is particularly important as hwasan_check_* instances are duplicated in every +// translation unit where HWASan is enabled. +// This function calls HwasanTagMismatch to step back into the C++ code that +// completes the stack unwinding and error printing. This function is is not +// permitted to return. + + +// | ... | +// | ... | +// | Previous stack frames... | +// +=================================+ +// | ... | +// | | +// | Stack frame space for x12 - x31.| +// | | +// | ... | +// +---------------------------------+ <-- [SP + 96] +// | Saved x11(arg1), as | +// | __hwasan_check_* clobbers it. | +// +---------------------------------+ <-- [SP + 88] +// | Saved x10(arg0), as | +// | __hwasan_check_* clobbers it. | +// +---------------------------------+ <-- [SP + 80] +// | | +// | Stack frame space for x9. | +// +---------------------------------+ <-- [SP + 72] +// | | +// | Saved x8(fp), as | +// | __hwasan_check_* clobbers it. | +// +---------------------------------+ <-- [SP + 64] +// | ... | +// | | +// | Stack frame space for x2 - x7. | +// | | +// | ... | +// +---------------------------------+ <-- [SP + 16] +// | Return address (x1) for caller | +// | of __hwasan_check_*. | +// +---------------------------------+ <-- [SP + 8] +// | Reserved place for x0, possibly | +// | junk, since we don't save it. | +// +---------------------------------+ <-- [x2 / SP] + +// This function takes two arguments: +// * x10/a0: The data address. +// * x11/a1: The encoded access info for the failing access. + +.section .text +.file "hwasan_tag_mismatch_riscv64.S" + +.global __hwasan_tag_mismatch_v2 +ASM_TYPE_FUNCTION(__hwasan_tag_mismatch_v2) +__hwasan_tag_mismatch_v2: + CFI_STARTPROC + + // Set the CFA to be the return address for caller of __hwasan_check_*. Note + // that we do not emit CFI predicates to describe the contents of this stack + // frame, as this proxy entry point should never be debugged. The contents + // are static and are handled by the unwinder after calling + // __hwasan_tag_mismatch. The frame pointer is already correctly setup + // by __hwasan_check_*. + addi fp, sp, 256 + CFI_DEF_CFA(fp, 0) + CFI_OFFSET(ra, -248) + CFI_OFFSET(fp, -192) + + // Save the rest of the registers into the preallocated space left by + // __hwasan_check. + sd x31, 248(sp) + sd x30, 240(sp) + sd x29, 232(sp) + sd x28, 224(sp) + sd x27, 216(sp) + sd x26, 208(sp) + sd x25, 200(sp) + sd x24, 192(sp) + sd x23, 184(sp) + sd x22, 176(sp) + sd x21, 168(sp) + sd x20, 160(sp) + sd x19, 152(sp) + sd x18, 144(sp) + sd x17, 136(sp) + sd x16, 128(sp) + sd x15, 120(sp) + sd x14, 112(sp) + sd x13, 104(sp) + sd x12, 96(sp) + // sd x11, 88(sp) ; already saved + // sd x10, 80(sp) ; already saved + sd x9, 72(sp) + // sd x8, 64(sp) ; already saved + sd x7, 56(sp) + sd x6, 48(sp) + sd x5, 40(sp) + sd x4, 32(sp) + sd x3, 24(sp) + sd x2, 16(sp) + // sd x1, 8(sp) ; already saved + // sd x0, 0(sp) ; don't store zero register + + // Pass the address of the frame to __hwasan_tag_mismatch4, so that it can + // extract the saved registers from this frame without having to worry about + // finding this frame. + mv x12, sp + + call __hwasan_tag_mismatch4 + CFI_ENDPROC +ASM_SIZE(__hwasan_tag_mismatch_v2) + +#endif // defined(__riscv) && (__riscv_xlen == 64) + +// We do not need executable stack. +NO_EXEC_STACK_DIRECTIVE diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_thread.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_thread.cpp index ee747a3beea..4a78f606290 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_thread.cpp +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_thread.cpp @@ -1,15 +1,16 @@ +#include "hwasan_thread.h" + #include "hwasan.h" +#include "hwasan_interface_internal.h" #include "hwasan_mapping.h" -#include "hwasan_thread.h" #include "hwasan_poisoning.h" -#include "hwasan_interface_internal.h" - +#include "hwasan_thread_list.h" +#include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_file.h" #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_tls_get_addr.h" - namespace __hwasan { static u32 RandomSeed() { @@ -27,6 +28,7 @@ static u32 RandomSeed() { void Thread::InitRandomState() { random_state_ = flags()->random_tags ? RandomSeed() : unique_id_; + random_state_inited_ = true; // Push a random number of zeros onto the ring buffer so that the first stack // tag base will be random. @@ -40,18 +42,20 @@ void Thread::Init(uptr stack_buffer_start, uptr stack_buffer_size, CHECK_EQ(0, stack_top_); CHECK_EQ(0, stack_bottom_); - static u64 unique_id; - unique_id_ = unique_id++; + static atomic_uint64_t unique_id; + unique_id_ = atomic_fetch_add(&unique_id, 1, memory_order_relaxed); + if (auto sz = flags()->heap_history_size) heap_allocations_ = HeapAllocationsRingBuffer::New(sz); - InitStackAndTls(state); #if !SANITIZER_FUCHSIA // Do not initialize the stack ring buffer just yet on Fuchsia. Threads will // be initialized before we enter the thread itself, so we will instead call // this later. InitStackRingBuffer(stack_buffer_start, stack_buffer_size); #endif + InitStackAndTls(state); + dtls_ = DTLS_Get(); } void Thread::InitStackRingBuffer(uptr stack_buffer_start, @@ -108,10 +112,9 @@ void Thread::Destroy() { } void Thread::Print(const char *Prefix) { - Printf("%sT%zd %p stack: [%p,%p) sz: %zd tls: [%p,%p)\n", Prefix, - unique_id_, this, stack_bottom(), stack_top(), - stack_top() - stack_bottom(), - tls_begin(), tls_end()); + Printf("%sT%zd %p stack: [%p,%p) sz: %zd tls: [%p,%p)\n", Prefix, unique_id_, + (void *)this, stack_bottom(), stack_top(), + stack_top() - stack_bottom(), tls_begin(), tls_end()); } static u32 xorshift(u32 state) { @@ -124,17 +127,21 @@ static u32 xorshift(u32 state) { // Generate a (pseudo-)random non-zero tag. tag_t Thread::GenerateRandomTag(uptr num_bits) { DCHECK_GT(num_bits, 0); - if (tagging_disabled_) return 0; + if (tagging_disabled_) + return 0; tag_t tag; const uptr tag_mask = (1ULL << num_bits) - 1; do { if (flags()->random_tags) { - if (!random_buffer_) + if (!random_buffer_) { + EnsureRandomStateInited(); random_buffer_ = random_state_ = xorshift(random_state_); + } CHECK(random_buffer_); tag = random_buffer_ & tag_mask; random_buffer_ >>= num_bits; } else { + EnsureRandomStateInited(); random_state_ += 1; tag = random_state_ & tag_mask; } @@ -143,3 +150,55 @@ tag_t Thread::GenerateRandomTag(uptr num_bits) { } } // namespace __hwasan + +// --- Implementation of LSan-specific functions --- {{{1 +namespace __lsan { + +static __hwasan::HwasanThreadList *GetHwasanThreadListLocked() { + auto &tl = __hwasan::hwasanThreadList(); + tl.CheckLocked(); + return &tl; +} + +static __hwasan::Thread *GetThreadByOsIDLocked(tid_t os_id) { + return GetHwasanThreadListLocked()->FindThreadLocked( + [os_id](__hwasan::Thread *t) { return t->os_id() == os_id; }); +} + +void LockThreadRegistry() { __hwasan::hwasanThreadList().Lock(); } + +void UnlockThreadRegistry() { __hwasan::hwasanThreadList().Unlock(); } + +void EnsureMainThreadIDIsCorrect() { + auto *t = __hwasan::GetCurrentThread(); + if (t && (t->IsMainThread())) + t->set_os_id(GetTid()); +} + +bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end, + uptr *tls_begin, uptr *tls_end, uptr *cache_begin, + uptr *cache_end, DTLS **dtls) { + auto *t = GetThreadByOsIDLocked(os_id); + if (!t) + return false; + *stack_begin = t->stack_bottom(); + *stack_end = t->stack_top(); + *tls_begin = t->tls_begin(); + *tls_end = t->tls_end(); + // Fixme: is this correct for HWASan. + *cache_begin = 0; + *cache_end = 0; + *dtls = t->dtls(); + return true; +} + +void GetAllThreadAllocatorCachesLocked(InternalMmapVector *caches) {} + +void GetThreadExtraStackRangesLocked(tid_t os_id, + InternalMmapVector *ranges) {} +void GetThreadExtraStackRangesLocked(InternalMmapVector *ranges) {} + +void GetAdditionalThreadContextPtrsLocked(InternalMmapVector *ptrs) {} +void GetRunningThreadsLocked(InternalMmapVector *threads) {} + +} // namespace __lsan diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_thread.h b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_thread.h index 9f20afe1dc7..9727585ef75 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_thread.h +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_thread.h @@ -28,12 +28,17 @@ class Thread { void Init(uptr stack_buffer_start, uptr stack_buffer_size, const InitState *state = nullptr); - void InitRandomState(); + void InitStackAndTls(const InitState *state = nullptr); // Must be called from the thread itself. void InitStackRingBuffer(uptr stack_buffer_start, uptr stack_buffer_size); + inline void EnsureRandomStateInited() { + if (UNLIKELY(!random_state_inited_)) + InitRandomState(); + } + void Destroy(); uptr stack_top() { return stack_top_; } @@ -41,6 +46,7 @@ class Thread { uptr stack_size() { return stack_top() - stack_bottom(); } uptr tls_begin() { return tls_begin_; } uptr tls_end() { return tls_end_; } + DTLS *dtls() { return dtls_; } bool IsMainThread() { return unique_id_ == 0; } bool AddrIsInStack(uptr addr) { @@ -56,13 +62,16 @@ class Thread { void DisableTagging() { tagging_disabled_++; } void EnableTagging() { tagging_disabled_--; } - u64 unique_id() const { return unique_id_; } + u32 unique_id() const { return unique_id_; } void Announce() { if (announced_) return; announced_ = true; Print("Thread: "); } + tid_t os_id() const { return os_id_; } + void set_os_id(tid_t os_id) { os_id_ = os_id; } + uptr &vfork_spill() { return vfork_spill_; } private: @@ -70,11 +79,13 @@ class Thread { // via mmap() and *must* be valid in zero-initialized state. void ClearShadowForThreadStackAndTLS(); void Print(const char *prefix); + void InitRandomState(); uptr vfork_spill_; uptr stack_top_; uptr stack_bottom_; uptr tls_begin_; uptr tls_end_; + DTLS *dtls_; u32 random_state_; u32 random_buffer_; @@ -83,12 +94,16 @@ class Thread { HeapAllocationsRingBuffer *heap_allocations_; StackAllocationsRingBuffer *stack_allocations_; - u64 unique_id_; // counting from zero. + u32 unique_id_; // counting from zero. + + tid_t os_id_; u32 tagging_disabled_; // if non-zero, malloc uses zero tag in this thread. bool announced_; + bool random_state_inited_; // Whether InitRandomState() has been called. + friend struct ThreadListHead; }; diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_thread_list.h b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_thread_list.h index 15916a802d6..97485b195b6 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_thread_list.h +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_thread_list.h @@ -71,7 +71,7 @@ struct ThreadStats { uptr total_stack_size; }; -class HwasanThreadList { +class SANITIZER_MUTEX HwasanThreadList { public: HwasanThreadList(uptr storage, uptr size) : free_space_(storage), free_space_end_(storage + size) { @@ -85,7 +85,8 @@ class HwasanThreadList { RoundUpTo(ring_buffer_size_ + sizeof(Thread), ring_buffer_size_ * 2); } - Thread *CreateCurrentThread(const Thread::InitState *state = nullptr) { + Thread *CreateCurrentThread(const Thread::InitState *state = nullptr) + SANITIZER_EXCLUDES(free_list_mutex_, live_list_mutex_) { Thread *t = nullptr; { SpinMutexLock l(&free_list_mutex_); @@ -114,7 +115,8 @@ class HwasanThreadList { ReleaseMemoryPagesToOS(start, start + thread_alloc_size_); } - void RemoveThreadFromLiveList(Thread *t) { + void RemoveThreadFromLiveList(Thread *t) + SANITIZER_EXCLUDES(live_list_mutex_) { SpinMutexLock l(&live_list_mutex_); for (Thread *&t2 : live_list_) if (t2 == t) { @@ -127,7 +129,7 @@ class HwasanThreadList { CHECK(0 && "thread not found in live list"); } - void ReleaseThread(Thread *t) { + void ReleaseThread(Thread *t) SANITIZER_EXCLUDES(free_list_mutex_) { RemoveThreadStats(t); t->Destroy(); DontNeedThread(t); @@ -149,30 +151,47 @@ class HwasanThreadList { } template - void VisitAllLiveThreads(CB cb) { + void VisitAllLiveThreads(CB cb) SANITIZER_EXCLUDES(live_list_mutex_) { SpinMutexLock l(&live_list_mutex_); for (Thread *t : live_list_) cb(t); } - void AddThreadStats(Thread *t) { + template + Thread *FindThreadLocked(CB cb) SANITIZER_CHECK_LOCKED(stats_mutex_) { + CheckLocked(); + for (Thread *t : live_list_) + if (cb(t)) + return t; + return nullptr; + } + + void AddThreadStats(Thread *t) SANITIZER_EXCLUDES(stats_mutex_) { SpinMutexLock l(&stats_mutex_); stats_.n_live_threads++; stats_.total_stack_size += t->stack_size(); } - void RemoveThreadStats(Thread *t) { + void RemoveThreadStats(Thread *t) SANITIZER_EXCLUDES(stats_mutex_) { SpinMutexLock l(&stats_mutex_); stats_.n_live_threads--; stats_.total_stack_size -= t->stack_size(); } - ThreadStats GetThreadStats() { + ThreadStats GetThreadStats() SANITIZER_EXCLUDES(stats_mutex_) { SpinMutexLock l(&stats_mutex_); return stats_; } uptr GetRingBufferSize() const { return ring_buffer_size_; } + void Lock() SANITIZER_ACQUIRE(live_list_mutex_) { live_list_mutex_.Lock(); } + void CheckLocked() const SANITIZER_CHECK_LOCKED(live_list_mutex_) { + live_list_mutex_.CheckLocked(); + } + void Unlock() SANITIZER_RELEASE(live_list_mutex_) { + live_list_mutex_.Unlock(); + } + private: Thread *AllocThread() { SpinMutexLock l(&free_space_mutex_); @@ -191,12 +210,14 @@ class HwasanThreadList { uptr thread_alloc_size_; SpinMutex free_list_mutex_; - InternalMmapVector free_list_; + InternalMmapVector free_list_ + SANITIZER_GUARDED_BY(free_list_mutex_); SpinMutex live_list_mutex_; - InternalMmapVector live_list_; + InternalMmapVector live_list_ + SANITIZER_GUARDED_BY(live_list_mutex_); - ThreadStats stats_; SpinMutex stats_mutex_; + ThreadStats stats_ SANITIZER_GUARDED_BY(stats_mutex_); }; void InitThreadList(uptr storage, uptr size); diff --git a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_type_test.cpp b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_type_test.cpp index 8cff495bae1..5307073fb40 100644 --- a/gnu/llvm/compiler-rt/lib/hwasan/hwasan_type_test.cpp +++ b/gnu/llvm/compiler-rt/lib/hwasan/hwasan_type_test.cpp @@ -19,7 +19,7 @@ #define CHECK_TYPE_SIZE_FITS(TYPE) \ COMPILER_CHECK(sizeof(__hw_##TYPE) <= sizeof(TYPE)) -#if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__) +#if HWASAN_WITH_INTERCEPTORS CHECK_TYPE_SIZE_FITS(jmp_buf); CHECK_TYPE_SIZE_FITS(sigjmp_buf); #endif diff --git a/gnu/llvm/compiler-rt/lib/hwasan/scripts/hwasan_symbolize b/gnu/llvm/compiler-rt/lib/hwasan/scripts/hwasan_symbolize index dd5f859561e..0408e0eb999 100755 --- a/gnu/llvm/compiler-rt/lib/hwasan/scripts/hwasan_symbolize +++ b/gnu/llvm/compiler-rt/lib/hwasan/scripts/hwasan_symbolize @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 #===- lib/hwasan/scripts/hwasan_symbolize ----------------------------------===# # # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -10,16 +10,91 @@ # HWAddressSanitizer offline symbolization script. # #===------------------------------------------------------------------------===# + +from __future__ import print_function +from __future__ import unicode_literals + +import argparse import glob +import html +import json +import mmap import os import re -import sys -import string +import struct import subprocess -import argparse +import sys -last_access_address = None -last_access_tag = None +if sys.version_info.major < 3: + # Simulate Python 3.x behaviour of defaulting to UTF-8 for print. This is + # important in case any symbols are non-ASCII. + import codecs + sys.stdout = codecs.getwriter("utf-8")(sys.stdout) + +# Below, a parser for a subset of ELF. It only supports 64 bit, little-endian, +# and only parses what is necessary to find the build ids. It uses a memoryview +# into an mmap to avoid copying. +Ehdr_size = 64 +e_shnum_offset = 60 +e_shoff_offset = 40 + +Shdr_size = 64 +sh_type_offset = 4 +sh_offset_offset = 24 +sh_size_offset = 32 +SHT_NOTE = 7 + +Nhdr_size = 12 +NT_GNU_BUILD_ID = 3 + +def align_up(size, alignment): + return (size + alignment - 1) & ~(alignment - 1) + +def handle_Nhdr(mv, sh_size): + offset = 0 + while offset < sh_size: + n_namesz, n_descsz, n_type = struct.unpack_from(' 2: + opt['encoding'] = 'utf-8' + self.__pipe = subprocess.Popen([self.__path, "--inlining", "--functions"], + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + **opt) + + class __EOF(Exception): pass def __write(self, s): - print >>self.__pipe.stdin, s + print(s, file=self.__pipe.stdin) + self.__pipe.stdin.flush() if self.__log: - print >>sys.stderr, ("#>> |%s|" % (s,)) + print("#>> |%s|" % (s,), file=sys.stderr) def __read(self): s = self.__pipe.stdout.readline().rstrip() if self.__log: - print >>sys.stderr, ("# << |%s|" % (s,)) + print("# << |%s|" % (s,), file=sys.stderr) if s == '': raise Symbolizer.__EOF return s @@ -62,27 +175,35 @@ class Symbolizer: file_name = re.sub(".*crtstuff.c:0", "???:0", file_name) return file_name - def __process_binary_name(self, name): + def __process_binary_name(self, name, buildid): if name.startswith('/'): name = name[1:] + if buildid is not None and buildid in self.__index: + return self.__index[buildid] + for p in self.__binary_prefixes: full_path = os.path.join(p, name) if os.path.exists(full_path): return full_path + apex_prefix = "apex/com.android." + if name.startswith(apex_prefix): + full_path = os.path.join(p, "apex/com.google.android." + name[len(apex_prefix):]) + if os.path.exists(full_path): + return full_path # Try stripping extra path components as the last resort. for p in self.__binary_prefixes: full_path = os.path.join(p, os.path.basename(name)) if os.path.exists(full_path): return full_path if name not in self.__warnings: - print >>sys.stderr, "Could not find symbols for", name + print("Could not find symbols for", name, file=sys.stderr) self.__warnings.add(name) return None - def iter_locals(self, binary, addr): + def iter_locals(self, binary, addr, buildid): self.__open_pipe() p = self.__pipe - binary = self.__process_binary_name(binary) + binary = self.__process_binary_name(binary, buildid) if not binary: return self.__write("FRAME %s %s" % (binary, addr)) @@ -101,10 +222,10 @@ class Symbolizer: except Symbolizer.__EOF: pass - def iter_call_stack(self, binary, addr): + def iter_call_stack(self, binary, buildid, addr): self.__open_pipe() p = self.__pipe - binary = self.__process_binary_name(binary) + binary = self.__process_binary_name(binary, buildid) if not binary: return self.__write("CODE %s %s" % (binary, addr)) @@ -117,133 +238,116 @@ class Symbolizer: except Symbolizer.__EOF: pass -def symbolize_line(line, symbolizer_path): - #0 0x7f6e35cf2e45 (/blah/foo.so+0x11fe45) - match = re.match(r'^(.*?)#([0-9]+)( *)(0x[0-9a-f]*) *\((.*)\+(0x[0-9a-f]+)\)', line, re.UNICODE) - if match: - frameno = match.group(2) - binary = match.group(5) - addr = int(match.group(6), 16) - - frames = list(symbolizer.iter_call_stack(binary, addr)) - - if len(frames) > 0: - print "%s#%s%s%s in %s" % (match.group(1).encode('utf-8'), match.group(2).encode('utf-8'), - match.group(3).encode('utf-8'), frames[0][0], frames[0][1]) - for i in range(1, len(frames)): - space1 = ' ' * match.end(1) - space2 = ' ' * (match.start(4) - match.end(1) - 2) - print "%s->%s%s in %s" % (space1, space2, frames[i][0], frames[i][1]) + def maybe_linkify(self, file_line): + if not self.__html or not self.__link_prefixes: + return file_line + filename, line_col = file_line.split(':', 1) + if not line_col: + line = '0' # simplify the link generation else: - print line.rstrip().encode('utf-8') - else: - print line.rstrip().encode('utf-8') - -def save_access_address(line): - global last_access_address, last_access_tag - match = re.match(r'^(.*?)HWAddressSanitizer: tag-mismatch on address (0x[0-9a-f]+) ', line, re.UNICODE) - if match: - last_access_address = int(match.group(2), 16) - match = re.match(r'^(.*?) of size [0-9]+ at 0x[0-9a-f]* tags: ([0-9a-f]+)/[0-9a-f]+ \(ptr/mem\)', line, re.UNICODE) - if match: - last_access_tag = int(match.group(2), 16) - -def process_stack_history(line, symbolizer, ignore_tags=False): - if last_access_address is None or last_access_tag is None: - return - if re.match(r'Previously allocated frames:', line, re.UNICODE): - return True - pc_mask = (1 << 48) - 1 - fp_mask = (1 << 20) - 1 - # record_addr:0x1234ABCD record:0x1234ABCD (/path/to/binary+0x1234ABCD) - match = re.match(r'^(.*?)record_addr:(0x[0-9a-f]+) +record:(0x[0-9a-f]+) +\((.*)\+(0x[0-9a-f]+)\)', line, re.UNICODE) - if match: - record_addr = int(match.group(2), 16) - record = int(match.group(3), 16) - binary = match.group(4) - addr = int(match.group(5), 16) - base_tag = (record_addr >> 3) & 0xFF - fp = (record >> 48) << 4 - pc = record & pc_mask - - for local in symbolizer.iter_locals(binary, addr): - frame_offset = local[3] - size = local[4] - if frame_offset is None or size is None: - continue - obj_offset = (last_access_address - fp - frame_offset) & fp_mask - if obj_offset >= size: - continue - tag_offset = local[5] - if not ignore_tags and (tag_offset is None or base_tag ^ tag_offset != last_access_tag): - continue - print '' - print 'Potentially referenced stack object:' - print ' %d bytes inside variable "%s" in stack frame of function "%s"' % (obj_offset, local[2], local[0]) - print ' at %s' % (local[1],) - return True - return False - -parser = argparse.ArgumentParser() -parser.add_argument('-d', action='store_true') -parser.add_argument('-v', action='store_true') -parser.add_argument('--ignore-tags', action='store_true') -parser.add_argument('--symbols', action='append') -parser.add_argument('--source', action='append') -parser.add_argument('--symbolizer') -parser.add_argument('args', nargs=argparse.REMAINDER) -args = parser.parse_args() - -# Unstripped binaries location. -binary_prefixes = args.symbols or [] -if not binary_prefixes: - if 'ANDROID_PRODUCT_OUT' in os.environ: - product_out = os.path.join(os.environ['ANDROID_PRODUCT_OUT'], 'symbols') - binary_prefixes.append(product_out) - -for p in binary_prefixes: - if not os.path.isdir(p): - print >>sys.stderr, "Symbols path does not exist or is not a directory:", p - sys.exit(1) - -# Source location. -paths_to_cut = args.source or [] -if not paths_to_cut: - paths_to_cut.append(os.getcwd() + '/') - if 'ANDROID_BUILD_TOP' in os.environ: - paths_to_cut.append(os.environ['ANDROID_BUILD_TOP'] + '/') - -# llvm-symbolizer binary. -# 1. --symbolizer flag -# 2. environment variable -# 3. unsuffixed binary in the current directory -# 4. if inside Android platform, prebuilt binary at a known path -# 5. first "llvm-symbolizer", then "llvm-symbolizer-$VER" with the -# highest available version in $PATH -symbolizer_path = args.symbolizer -if not symbolizer_path: - if 'LLVM_SYMBOLIZER_PATH' in os.environ: - symbolizer_path = os.environ['LLVM_SYMBOLIZER_PATH'] - elif 'HWASAN_SYMBOLIZER_PATH' in os.environ: - symbolizer_path = os.environ['HWASAN_SYMBOLIZER_PATH'] - -if not symbolizer_path: - s = os.path.join(os.path.dirname(sys.argv[0]), 'llvm-symbolizer') - if os.path.exists(s): - symbolizer_path = s - -if not symbolizer_path: - if 'ANDROID_BUILD_TOP' in os.environ: - s = os.path.join(os.environ['ANDROID_BUILD_TOP'], 'prebuilts/clang/host/linux-x86/llvm-binutils-stable/llvm-symbolizer') - if os.path.exists(s): - symbolizer_path = s + line = line_col.split(':')[0] + longest_prefix = max(( + (prefix, link) for prefix, link in self.__link_prefixes + if filename.startswith(prefix)), + key=lambda x: len(x[0]), default=None) + if longest_prefix is None: + return file_line + else: + prefix, link = longest_prefix + return '{}'.format( + html.escape(link.format(file=filename[len(prefix):], line=line, + file_line=file_line, prefix=prefix)), file_line) -if not symbolizer_path: - for path in os.environ["PATH"].split(os.pathsep): - p = os.path.join(path, 'llvm-symbolizer') - if os.path.exists(p): - symbolizer_path = p - break + def build_index(self): + for p in self.__binary_prefixes: + for dname, _, fnames in os.walk(p): + for fn in fnames: + filename = os.path.join(dname, fn) + try: + bid = get_buildid(filename) + except FileNotFoundError: + continue + except Exception as e: + print("Failed to parse {}: {}".format(filename, e), file=sys.stderr) + continue + if bid is not None: + self.__index[bid] = filename + + def symbolize_line(self, line): + #0 0x7f6e35cf2e45 (/blah/foo.so+0x11fe45) (BuildId: 4abce4cd41ea5c2f34753297b7e774d9) + match = re.match(r'^(.*?)#([0-9]+)( *)(0x[0-9a-f]*) *\((.*)\+(0x[0-9a-f]+)\)' + r'(?:\s*\(BuildId: ([0-9a-f]+)\))?', line, re.UNICODE) + if match: + frameno = match.group(2) + binary = match.group(5) + addr = int(match.group(6), 16) + buildid = match.group(7) + + frames = list(self.iter_call_stack(binary, buildid, addr)) + + if len(frames) > 0: + self.print( + self.maybe_escape( + "%s#%s%s%s in " % (match.group(1), match.group(2), match.group(3), + frames[0][0]) + ) + self.maybe_linkify(frames[0][1]), + escape=False) + for i in range(1, len(frames)): + space1 = ' ' * match.end(1) + space2 = ' ' * (match.start(4) - match.end(1) - 2) + self.print( + self.maybe_escape("%s->%s%s in " % (space1, space2, frames[i][0])) + + self.maybe_linkify(frames[i][1]), escape=False) + else: + self.print(line.rstrip()) + else: + self.print(line.rstrip()) + + def save_access_address(self, line): + match = re.match(r'^(.*?)HWAddressSanitizer: tag-mismatch on address (0x[0-9a-f]+) ', line, re.UNICODE) + if match: + self.__last_access_address = int(match.group(2), 16) + match = re.match(r'^(.*?) of size [0-9]+ at 0x[0-9a-f]* tags: ([0-9a-f]+)/[0-9a-f]+(\([0-9a-f]+\))? \(ptr/mem\)', line, re.UNICODE) + if match: + self.__last_access_tag = int(match.group(2), 16) + + def process_stack_history(self, line, ignore_tags=False): + if self.__last_access_address is None or self.__last_access_tag is None: + return + if re.match(r'Previously allocated frames:', line, re.UNICODE): + return True + pc_mask = (1 << 48) - 1 + fp_mask = (1 << 20) - 1 + # record_addr:0x1234ABCD record:0x1234ABCD (/path/to/binary+0x1234ABCD) (BuildId: 4abce4cd41ea5c2f34753297b7e774d9) + match = re.match(r'^(.*?)record_addr:(0x[0-9a-f]+) +record:(0x[0-9a-f]+) +\((.*)\+(0x[0-9a-f]+)\)' + r'(?:\s*\(BuildId: ([0-9a-f]+)\))?', line, re.UNICODE) + if match: + record_addr = int(match.group(2), 16) + record = int(match.group(3), 16) + binary = match.group(4) + addr = int(match.group(5), 16) + buildid = match.group(6) + base_tag = (record_addr >> 3) & 0xFF + fp = (record >> 48) << 4 + pc = record & pc_mask + + for local in self.iter_locals(binary, addr, buildid): + frame_offset = local[3] + size = local[4] + if frame_offset is None or size is None: + continue + obj_offset = (self.__last_access_address - fp - frame_offset) & fp_mask + if obj_offset >= size: + continue + tag_offset = local[5] + if not ignore_tags and (tag_offset is None or base_tag ^ tag_offset != self.__last_access_tag): + continue + self.print('') + self.print('Potentially referenced stack object:') + self.print(' %d bytes inside a variable "%s" in stack frame of function "%s"' % (obj_offset, local[2], local[0])) + self.print(' at %s' % (local[1],)) + return True + return False def extract_version(s): idx = s.rfind('-') @@ -252,34 +356,114 @@ def extract_version(s): x = float(s[idx + 1:]) return x -if not symbolizer_path: - for path in os.environ["PATH"].split(os.pathsep): - candidates = glob.glob(os.path.join(path, 'llvm-symbolizer-*')) - if len(candidates) > 0: - candidates.sort(key = extract_version, reverse = True) - symbolizer_path = candidates[0] - break - -if not os.path.exists(symbolizer_path): - print >>sys.stderr, "Symbolizer path does not exist:", symbolizer_path - sys.exit(1) - -if args.v: - print "Looking for symbols in:" - for s in binary_prefixes: - print " %s" % (s,) - print "Stripping source path prefixes:" - for s in paths_to_cut: - print " %s" % (s,) - print "Using llvm-symbolizer binary in:\n %s" % (symbolizer_path,) - print - -symbolizer = Symbolizer(symbolizer_path, binary_prefixes, paths_to_cut) -symbolizer.enable_logging(args.d) - -for line in sys.stdin: - line = line.decode('utf-8') - save_access_address(line) - if process_stack_history(line, symbolizer, ignore_tags=args.ignore_tags): - continue - symbolize_line(line, symbolizer_path) +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('-d', action='store_true') + parser.add_argument('-v', action='store_true') + parser.add_argument('--ignore-tags', action='store_true') + parser.add_argument('--symbols', action='append') + parser.add_argument('--source', action='append') + parser.add_argument('--index', action='store_true') + parser.add_argument('--symbolizer') + parser.add_argument('--linkify', type=str) + parser.add_argument('--html', action='store_true') + parser.add_argument('args', nargs=argparse.REMAINDER) + args = parser.parse_args() + + # Unstripped binaries location. + binary_prefixes = args.symbols or [] + if not binary_prefixes: + if 'ANDROID_PRODUCT_OUT' in os.environ: + product_out = os.path.join(os.environ['ANDROID_PRODUCT_OUT'], 'symbols') + binary_prefixes.append(product_out) + binary_prefixes.append('/') + + for p in binary_prefixes: + if not os.path.isdir(p): + print("Symbols path does not exist or is not a directory:", p, file=sys.stderr) + sys.exit(1) + + # Source location. + paths_to_cut = args.source or [] + if not paths_to_cut: + paths_to_cut.append(os.getcwd() + '/') + if 'ANDROID_BUILD_TOP' in os.environ: + paths_to_cut.append(os.environ['ANDROID_BUILD_TOP'] + '/') + + # llvm-symbolizer binary. + # 1. --symbolizer flag + # 2. environment variable + # 3. unsuffixed binary in the current directory + # 4. if inside Android platform, prebuilt binary at a known path + # 5. first "llvm-symbolizer", then "llvm-symbolizer-$VER" with the + # highest available version in $PATH + symbolizer_path = args.symbolizer + if not symbolizer_path: + if 'LLVM_SYMBOLIZER_PATH' in os.environ: + symbolizer_path = os.environ['LLVM_SYMBOLIZER_PATH'] + elif 'HWASAN_SYMBOLIZER_PATH' in os.environ: + symbolizer_path = os.environ['HWASAN_SYMBOLIZER_PATH'] + + if not symbolizer_path: + s = os.path.join(os.path.dirname(sys.argv[0]), 'llvm-symbolizer') + if os.path.exists(s): + symbolizer_path = s + + if not symbolizer_path: + if 'ANDROID_BUILD_TOP' in os.environ: + s = os.path.join(os.environ['ANDROID_BUILD_TOP'], 'prebuilts/clang/host/linux-x86/llvm-binutils-stable/llvm-symbolizer') + if os.path.exists(s): + symbolizer_path = s + + if not symbolizer_path: + for path in os.environ["PATH"].split(os.pathsep): + p = os.path.join(path, 'llvm-symbolizer') + if os.path.exists(p): + symbolizer_path = p + break + + if not symbolizer_path: + for path in os.environ["PATH"].split(os.pathsep): + candidates = glob.glob(os.path.join(path, 'llvm-symbolizer-*')) + if len(candidates) > 0: + candidates.sort(key = extract_version, reverse = True) + symbolizer_path = candidates[0] + break + + if not os.path.exists(symbolizer_path): + print("Symbolizer path does not exist:", symbolizer_path, file=sys.stderr) + sys.exit(1) + + if args.v: + print("Looking for symbols in:") + for s in binary_prefixes: + print(" %s" % (s,)) + print("Stripping source path prefixes:") + for s in paths_to_cut: + print(" %s" % (s,)) + print("Using llvm-symbolizer binary in:\n %s" % (symbolizer_path,)) + print() + + symbolizer = Symbolizer(symbolizer_path, binary_prefixes, paths_to_cut) + symbolizer.enable_html(args.html) + symbolizer.enable_logging(args.d) + if args.index: + symbolizer.build_index() + + if args.linkify: + if not args.html: + print('Need --html to --linkify', file=sys.stderr) + sys.exit(1) + symbolizer.read_linkify(args.linkify) + + for line in sys.stdin: + if sys.version_info.major < 3: + line = line.decode('utf-8') + symbolizer.save_access_address(line) + if symbolizer.process_stack_history(line, ignore_tags=args.ignore_tags): + continue + symbolizer.symbolize_line(line) + + +if __name__ == '__main__': + main() diff --git a/gnu/llvm/compiler-rt/lib/interception/CMakeLists.txt b/gnu/llvm/compiler-rt/lib/interception/CMakeLists.txt index 58ae79902c7..3242cf50e35 100644 --- a/gnu/llvm/compiler-rt/lib/interception/CMakeLists.txt +++ b/gnu/llvm/compiler-rt/lib/interception/CMakeLists.txt @@ -19,6 +19,11 @@ include_directories(..) set(INTERCEPTION_CFLAGS ${SANITIZER_COMMON_CFLAGS}) append_rtti_flag(OFF INTERCEPTION_CFLAGS) +# Silence warnings in system headers with MSVC. +if(NOT CLANG_CL) + append_list_if(COMPILER_RT_HAS_EXTERNAL_FLAG "/experimental:external /external:W0 /external:anglebrackets" INTERCEPTION_CFLAGS) +endif() + add_compiler_rt_object_libraries(RTInterception OS ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} diff --git a/gnu/llvm/compiler-rt/lib/interception/interception_mac.cpp b/gnu/llvm/compiler-rt/lib/interception/interception_mac.cpp index fb6eadcff59..03eae0fdca0 100644 --- a/gnu/llvm/compiler-rt/lib/interception/interception_mac.cpp +++ b/gnu/llvm/compiler-rt/lib/interception/interception_mac.cpp @@ -13,6 +13,6 @@ #include "interception.h" -#if SANITIZER_MAC +#if SANITIZER_APPLE -#endif // SANITIZER_MAC +#endif // SANITIZER_APPLE diff --git a/gnu/llvm/compiler-rt/lib/interception/interception_mac.h b/gnu/llvm/compiler-rt/lib/interception/interception_mac.h index eddedb8959c..26079518c64 100644 --- a/gnu/llvm/compiler-rt/lib/interception/interception_mac.h +++ b/gnu/llvm/compiler-rt/lib/interception/interception_mac.h @@ -11,7 +11,7 @@ // Mac-specific interception methods. //===----------------------------------------------------------------------===// -#if SANITIZER_MAC +#if SANITIZER_APPLE #if !defined(INCLUDED_FROM_INTERCEPTION_LIB) # error "interception_mac.h should be included from interception.h only" @@ -24,4 +24,4 @@ #define INTERCEPT_FUNCTION_VER_MAC(func, symver) #endif // INTERCEPTION_MAC_H -#endif // SANITIZER_MAC +#endif // SANITIZER_APPLE diff --git a/gnu/llvm/compiler-rt/lib/interception/interception_type_test.cpp b/gnu/llvm/compiler-rt/lib/interception/interception_type_test.cpp index a611604a700..7c3de82a1e8 100644 --- a/gnu/llvm/compiler-rt/lib/interception/interception_type_test.cpp +++ b/gnu/llvm/compiler-rt/lib/interception/interception_type_test.cpp @@ -13,7 +13,7 @@ #include "interception.h" -#if SANITIZER_LINUX || SANITIZER_MAC +#if SANITIZER_LINUX || SANITIZER_APPLE #include #include @@ -24,9 +24,9 @@ COMPILER_CHECK(sizeof(::SSIZE_T) == sizeof(ssize_t)); COMPILER_CHECK(sizeof(::PTRDIFF_T) == sizeof(ptrdiff_t)); COMPILER_CHECK(sizeof(::INTMAX_T) == sizeof(intmax_t)); -#if !SANITIZER_MAC +# if SANITIZER_GLIBC || SANITIZER_ANDROID COMPILER_CHECK(sizeof(::OFF64_T) == sizeof(off64_t)); -#endif +# endif // The following are the cases when pread (and friends) is used instead of // pread64. In those cases we need OFF_T to match off_t. We don't care about the diff --git a/gnu/llvm/compiler-rt/lib/interception/interception_win.cpp b/gnu/llvm/compiler-rt/lib/interception/interception_win.cpp index 98bc756ae53..faaa8ee1538 100644 --- a/gnu/llvm/compiler-rt/lib/interception/interception_win.cpp +++ b/gnu/llvm/compiler-rt/lib/interception/interception_win.cpp @@ -56,7 +56,7 @@ // tramp: jmp QWORD [addr] // addr: .bytes // -// Note: is equilavent to