diff --git a/build/sanitizers/sanitizer_options.cc b/build/sanitizers/sanitizer_options.cc index 6c347210b4c..2ebe9ebce04 100644 --- a/build/sanitizers/sanitizer_options.cc +++ b/build/sanitizers/sanitizer_options.cc @@ -16,8 +16,7 @@ extern "C" void _sanitizer_options_link_helper() {} // callbacks are not sanitizer-instrumented, and that they aren't stripped by // the linker. #define SANITIZER_HOOK_ATTRIBUTE \ - extern "C" __attribute__((no_sanitize_address)) \ - __attribute__((no_sanitize_memory)) __attribute__((no_sanitize_thread)) \ + extern "C" __attribute__((no_sanitize_thread)) \ __attribute__((visibility("default"))) __attribute__((used)) #endif diff --git a/runtime/bin/reference_counting.h b/runtime/bin/reference_counting.h index beaa34075f0..ce426f861f9 100644 --- a/runtime/bin/reference_counting.h +++ b/runtime/bin/reference_counting.h @@ -8,6 +8,7 @@ #include #include "platform/assert.h" +#include "platform/globals.h" namespace dart { namespace bin { diff --git a/runtime/platform/BUILD.gn b/runtime/platform/BUILD.gn index 7f319e92f9d..0bd32ee9ae2 100644 --- a/runtime/platform/BUILD.gn +++ b/runtime/platform/BUILD.gn @@ -11,7 +11,6 @@ library_for_all_configs("libdart_platform") { sources = platform_sources include_dirs = [ ".." ] extra_deps = [] - configurable_deps = [ ":libdart_platform_no_tsan" ] if (is_fuchsia) { extra_deps += [ @@ -20,20 +19,3 @@ library_for_all_configs("libdart_platform") { ] } } - -config("no_tsan_config") { - if (!is_win) { - cflags = [ "-fno-sanitize=thread" ] - } -} - -library_for_all_configs("libdart_platform_no_tsan") { - target_type = "source_set" - public_configs = [ "../vm:libdart_vm_config" ] - extra_configs = [ ":no_tsan_config" ] - sources = [ - "no_tsan.cc", - "no_tsan.h", - ] - include_dirs = [ ".." ] -} diff --git a/runtime/platform/address_sanitizer.h b/runtime/platform/address_sanitizer.h index 22eddcae47a..8a5962afa95 100644 --- a/runtime/platform/address_sanitizer.h +++ b/runtime/platform/address_sanitizer.h @@ -19,7 +19,7 @@ #if defined(USING_ADDRESS_SANITIZER) extern "C" void __asan_unpoison_memory_region(void const volatile*, size_t); -#define NO_SANITIZE_ADDRESS __attribute__((no_sanitize("address"))) +#define NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) #define ASAN_UNPOISON(ptr, len) __asan_unpoison_memory_region(ptr, len) #else // defined(USING_ADDRESS_SANITIZER) #define NO_SANITIZE_ADDRESS diff --git a/runtime/platform/assert.h b/runtime/platform/assert.h index b786413d485..27ee57fb8fa 100644 --- a/runtime/platform/assert.h +++ b/runtime/platform/assert.h @@ -6,7 +6,6 @@ #define RUNTIME_PLATFORM_ASSERT_H_ #include "platform/globals.h" -#include "platform/memory_sanitizer.h" #if !defined(DEBUG) && !defined(NDEBUG) #error neither DEBUG nor NDEBUG defined diff --git a/runtime/platform/memory_sanitizer.h b/runtime/platform/memory_sanitizer.h index c56b8b1e23e..0da5d570ffe 100644 --- a/runtime/platform/memory_sanitizer.h +++ b/runtime/platform/memory_sanitizer.h @@ -36,7 +36,7 @@ extern "C" void __msan_check_mem_is_initialized(const volatile void*, size_t); #define MSAN_UNPOISON(ptr, len) __msan_unpoison(ptr, len) #define MSAN_CHECK_INITIALIZED(ptr, len) \ __msan_check_mem_is_initialized(ptr, len) -#define NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory"))) +#define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) #else // defined(USING_MEMORY_SANITIZER) #define MSAN_POISON(ptr, len) \ do { \ diff --git a/runtime/platform/no_tsan.cc b/runtime/platform/no_tsan.cc deleted file mode 100644 index 9611f4e97ce..00000000000 --- a/runtime/platform/no_tsan.cc +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "platform/no_tsan.h" - -namespace dart { - -#if defined(__clang__) - -#if defined(__has_feature) -#if __has_feature(thread_sanitizer) -#error Misconfigured build -#endif -#endif - -uintptr_t FetchAndRelaxedIgnoreRace(std::atomic* ptr, - uintptr_t value) { - return ptr->fetch_and(value, std::memory_order_relaxed); -} - -uintptr_t FetchOrRelaxedIgnoreRace(std::atomic* ptr, - uintptr_t value) { - return ptr->fetch_or(value, std::memory_order_relaxed); -} - -uintptr_t LoadRelaxedIgnoreRace(const std::atomic* ptr) { - return ptr->load(std::memory_order_relaxed); -} - -#endif // defined(__clang__) - -} // namespace dart diff --git a/runtime/platform/no_tsan.h b/runtime/platform/no_tsan.h index fe2248256a0..d763d2b3aa2 100644 --- a/runtime/platform/no_tsan.h +++ b/runtime/platform/no_tsan.h @@ -9,34 +9,39 @@ #include +#include "platform/thread_sanitizer.h" + namespace dart { -#if defined(__clang__) -// Clang does not honor no_sanitize(thread) for std::atomic, so we place -// the implementation in a separate compilation unit with TSAN disabled. -uintptr_t FetchAndRelaxedIgnoreRace(std::atomic* ptr, - uintptr_t value); -uintptr_t FetchOrRelaxedIgnoreRace(std::atomic* ptr, - uintptr_t value); -uintptr_t LoadRelaxedIgnoreRace(const std::atomic* ptr); -#else #if defined(__GNUC__) -__attribute__((no_sanitize("thread"))) -#endif +// GCC will do what we want with no_sanitize("thread") and std::atomic, but for +// Clang will need to use disable_sanitizer_instrumentation and the atomic +// builtins. +NO_SANITIZE_THREAD DISABLE_SANITIZER_INSTRUMENTATION inline uintptr_t +FetchAndRelaxedIgnoreRace(std::atomic* ptr, uintptr_t value) { + return __atomic_fetch_and(reinterpret_cast(ptr), value, + __ATOMIC_RELAXED); +} +NO_SANITIZE_THREAD DISABLE_SANITIZER_INSTRUMENTATION inline uintptr_t +FetchOrRelaxedIgnoreRace(std::atomic* ptr, uintptr_t value) { + return __atomic_fetch_or(reinterpret_cast(ptr), value, + __ATOMIC_RELAXED); +} +NO_SANITIZE_THREAD DISABLE_SANITIZER_INSTRUMENTATION inline uintptr_t +LoadRelaxedIgnoreRace(const std::atomic* ptr) { + return __atomic_load_n(reinterpret_cast(ptr), + __ATOMIC_RELAXED); +} +#else +// MSVC doesn't support TSAN. inline uintptr_t FetchAndRelaxedIgnoreRace(std::atomic* ptr, uintptr_t value) { return ptr->fetch_and(value, std::memory_order_relaxed); } -#if defined(__GNUC__) -__attribute__((no_sanitize("thread"))) -#endif inline uintptr_t FetchOrRelaxedIgnoreRace(std::atomic* ptr, uintptr_t value) { return ptr->fetch_or(value, std::memory_order_relaxed); } -#if defined(__GNUC__) -__attribute__((no_sanitize("thread"))) -#endif inline uintptr_t LoadRelaxedIgnoreRace(const std::atomic* ptr) { return ptr->load(std::memory_order_relaxed); } diff --git a/runtime/platform/platform_sources.gni b/runtime/platform/platform_sources.gni index 27b58ef8a7c..62007a99741 100644 --- a/runtime/platform/platform_sources.gni +++ b/runtime/platform/platform_sources.gni @@ -21,6 +21,7 @@ platform_sources = [ "list_queue.h", "lockers.h", "memory_sanitizer.h", + "no_tsan.h", "safe_stack.h", "signal_blocker.h", "synchronization.h", diff --git a/runtime/platform/thread_sanitizer.h b/runtime/platform/thread_sanitizer.h index 3b4f3ccf317..42fef40a505 100644 --- a/runtime/platform/thread_sanitizer.h +++ b/runtime/platform/thread_sanitizer.h @@ -16,7 +16,14 @@ #endif #if defined(USING_THREAD_SANITIZER) -#define NO_SANITIZE_THREAD __attribute__((no_sanitize("thread"))) +#define NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) +#if defined(__clang__) +#define DISABLE_SANITIZER_INSTRUMENTATION \ + __attribute__((disable_sanitizer_instrumentation)) +#else +#define DISABLE_SANITIZER_INSTRUMENTATION +#endif + extern "C" uint32_t __tsan_atomic32_load(uint32_t* addr, int order); extern "C" void __tsan_atomic32_store(uint32_t* addr, uint32_t value, @@ -49,6 +56,7 @@ extern "C" void __tsan_func_entry(void* pc); extern "C" void __tsan_func_exit(); #else #define NO_SANITIZE_THREAD +#define DISABLE_SANITIZER_INSTRUMENTATION #endif #if defined(USING_THREAD_SANITIZER) diff --git a/runtime/tests/vm/dart/tsan/field_data_race_no_sanitize_test.dart b/runtime/tests/vm/dart/tsan/field_data_race_no_sanitize_test.dart index 7dfc31a5338..c1238e4e02d 100644 --- a/runtime/tests/vm/dart/tsan/field_data_race_no_sanitize_test.dart +++ b/runtime/tests/vm/dart/tsan/field_data_race_no_sanitize_test.dart @@ -12,7 +12,7 @@ import "package:expect/expect.dart"; import '../dylib_utils.dart'; class Box { - @pragma("vm:no-sanitize-thread") // __attribute__((no_sanitize("thread"))) + @pragma("vm:no-sanitize-thread") // __attribute__((no_sanitize_thread))) int foo = 0; } diff --git a/runtime/vm/compiler/assembler/assembler_arm64_test.cc b/runtime/vm/compiler/assembler/assembler_arm64_test.cc index 94dd5bcfbe0..94dca5375ac 100644 --- a/runtime/vm/compiler/assembler/assembler_arm64_test.cc +++ b/runtime/vm/compiler/assembler/assembler_arm64_test.cc @@ -5,6 +5,7 @@ #include "vm/globals.h" #if defined(TARGET_ARCH_ARM64) +#include "platform/thread_sanitizer.h" #include "vm/compiler/assembler/assembler.h" #include "vm/compiler/assembler/assembler_test.h" #include "vm/compiler/backend/locations.h" diff --git a/runtime/vm/compiler/backend/il_test.cc b/runtime/vm/compiler/backend/il_test.cc index 3083bcd3433..a2ccc4477ca 100644 --- a/runtime/vm/compiler/backend/il_test.cc +++ b/runtime/vm/compiler/backend/il_test.cc @@ -8,6 +8,7 @@ #include #include "platform/text_buffer.h" +#include "platform/thread_sanitizer.h" #include "platform/utils.h" #include "vm/class_id.h" #include "vm/compiler/assembler/disassembler.h" diff --git a/runtime/vm/compiler/backend/memory_copy_test.cc b/runtime/vm/compiler/backend/memory_copy_test.cc index f27e6541258..f764cc5c069 100644 --- a/runtime/vm/compiler/backend/memory_copy_test.cc +++ b/runtime/vm/compiler/backend/memory_copy_test.cc @@ -4,6 +4,7 @@ #include +#include "platform/thread_sanitizer.h" #include "vm/compiler/backend/il.h" #include "vm/compiler/backend/il_printer.h" #include "vm/compiler/backend/il_test_helper.h" diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc index b41522c92c1..4919b3aed45 100644 --- a/runtime/vm/compiler_test.cc +++ b/runtime/vm/compiler_test.cc @@ -4,6 +4,7 @@ #include "vm/compiler/jit/compiler.h" #include "platform/assert.h" +#include "platform/thread_sanitizer.h" #include "vm/class_finalizer.h" #include "vm/code_patcher.h" #include "vm/dart_api_impl.h" diff --git a/runtime/vm/flags.h b/runtime/vm/flags.h index 697dbea0984..0bab225f0c3 100644 --- a/runtime/vm/flags.h +++ b/runtime/vm/flags.h @@ -6,6 +6,8 @@ #define RUNTIME_VM_FLAGS_H_ #include "platform/assert.h" +#include "platform/memory_sanitizer.h" +#include "platform/thread_sanitizer.h" #include "vm/flag_list.h" #include "vm/globals.h" diff --git a/runtime/vm/heap/heap_test.cc b/runtime/vm/heap/heap_test.cc index c531f967ec0..1d1c3c7f04e 100644 --- a/runtime/vm/heap/heap_test.cc +++ b/runtime/vm/heap/heap_test.cc @@ -11,6 +11,7 @@ #include "platform/assert.h" #include "platform/no_tsan.h" +#include "platform/thread_sanitizer.h" #include "vm/class_finalizer.h" #include "vm/dart_api_impl.h" #include "vm/globals.h" diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc index 9c3166393c1..8acd404a8ac 100644 --- a/runtime/vm/heap/marker.cc +++ b/runtime/vm/heap/marker.cc @@ -6,6 +6,7 @@ #include "platform/assert.h" #include "platform/atomic.h" +#include "platform/thread_sanitizer.h" #include "vm/allocation.h" #include "vm/dart_api_state.h" #include "vm/heap/gc_shared.h" diff --git a/runtime/vm/heap/pointer_block.h b/runtime/vm/heap/pointer_block.h index 2fd796fdfbb..635d6339426 100644 --- a/runtime/vm/heap/pointer_block.h +++ b/runtime/vm/heap/pointer_block.h @@ -6,6 +6,7 @@ #define RUNTIME_VM_HEAP_POINTER_BLOCK_H_ #include "platform/assert.h" +#include "platform/memory_sanitizer.h" #include "vm/globals.h" #include "vm/os_thread.h" #include "vm/tagged_pointer.h" diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc index 7636cd73b65..c9902181216 100644 --- a/runtime/vm/heap/scavenger.cc +++ b/runtime/vm/heap/scavenger.cc @@ -6,6 +6,7 @@ #include "platform/assert.h" #include "platform/leak_sanitizer.h" +#include "platform/thread_sanitizer.h" #include "vm/class_id.h" #include "vm/compiler/runtime_api.h" #include "vm/dart.h" diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h index 056de9b1220..c002d147e18 100644 --- a/runtime/vm/isolate.h +++ b/runtime/vm/isolate.h @@ -17,6 +17,7 @@ #include "platform/assert.h" #include "platform/atomic.h" #include "platform/growable_array.h" +#include "platform/thread_sanitizer.h" #include "vm/class_table.h" #include "vm/dispatch_table.h" #include "vm/exceptions.h" diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 96802dd621e..2c1e9ae6265 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -2846,6 +2846,10 @@ void Object::InitializeObject(uword address, reinterpret_cast(address)->tags_ = tags; #if defined(HOST_HAS_FAST_WRITE_WRITE_FENCE) + // GCC warns that TSAN doesn't understand thread fences. +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic ignored "-Wtsan" +#endif std::atomic_thread_fence(std::memory_order_release); #endif } diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc index cdec9773dd3..8817bb13d3b 100644 --- a/runtime/vm/object_test.cc +++ b/runtime/vm/object_test.cc @@ -11,6 +11,10 @@ #include "bin/vmservice_impl.h" #include "platform/globals.h" +#include "platform/leak_sanitizer.h" +#include "platform/memory_sanitizer.h" +#include "platform/thread_sanitizer.h" +#include "platform/undefined_behavior_sanitizer.h" #include "vm/class_finalizer.h" #include "vm/closure_functions_cache.h" diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc index 7fc8c422e3e..ea1446b80dd 100644 --- a/runtime/vm/os_linux.cc +++ b/runtime/vm/os_linux.cc @@ -23,6 +23,7 @@ #include // NOLINT #include "platform/memory_sanitizer.h" +#include "platform/thread_sanitizer.h" #include "platform/utils.h" #include "vm/code_comments.h" #include "vm/code_observers.h" diff --git a/runtime/vm/os_thread.cc b/runtime/vm/os_thread.cc index a982366024e..e38d9141301 100644 --- a/runtime/vm/os_thread.cc +++ b/runtime/vm/os_thread.cc @@ -6,6 +6,7 @@ #include "platform/address_sanitizer.h" #include "platform/atomic.h" +#include "platform/memory_sanitizer.h" #include "vm/lockers.h" #include "vm/log.h" #include "vm/thread_interrupter.h" diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc index d5e1ce3c3b9..71bc40fff30 100644 --- a/runtime/vm/runtime_entry.cc +++ b/runtime/vm/runtime_entry.cc @@ -5300,7 +5300,7 @@ extern "C" void __tsan_func_exit() { } #else #define CASE(x) \ - extern "C" __attribute__((disable_sanitizer_instrumentation)) void \ + extern "C" NO_SANITIZE_THREAD DISABLE_SANITIZER_INSTRUMENTATION void \ jit_tsan_##x(void* addr) { \ __tsan_##x##_pc( \ addr, reinterpret_cast( \ diff --git a/runtime/vm/tsan_symbolize.cc b/runtime/vm/tsan_symbolize.cc index 78f6a6e0994..5aae1b668ab 100644 --- a/runtime/vm/tsan_symbolize.cc +++ b/runtime/vm/tsan_symbolize.cc @@ -142,7 +142,7 @@ typedef void (*AddFrame)(void* ctxt, // then symbolize using our normal PC descriptors, etc, but this function must // not call any function that has been instrumented by TSAN or it might deadlock // during __tsan_func_entry. -extern "C" __attribute__((disable_sanitizer_instrumentation)) void +extern "C" NO_SANITIZE_THREAD DISABLE_SANITIZER_INSTRUMENTATION void __tsan_symbolize_external_ex(uintptr_t pc, AddFrame add_frame, void* ctxt) { constexpr uintptr_t kExternalPCBit = 1ULL << 60; const uword lookup_pc = pc & ~kExternalPCBit;