1// Copyright 2019 The Marl Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef marl_sanitizers_h
16#define marl_sanitizers_h
17
18// Define ADDRESS_SANITIZER_ENABLED to 1 if the project was built with the
19// address sanitizer enabled (-fsanitize=address).
20#if defined(__SANITIZE_ADDRESS__)
21#define ADDRESS_SANITIZER_ENABLED 1
22#else // defined(__SANITIZE_ADDRESS__)
23#if defined(__clang__)
24#if __has_feature(address_sanitizer)
25#define ADDRESS_SANITIZER_ENABLED 1
26#endif // __has_feature(address_sanitizer)
27#endif // defined(__clang__)
28#endif // defined(__SANITIZE_ADDRESS__)
29
30// ADDRESS_SANITIZER_ONLY(X) resolves to X if ADDRESS_SANITIZER_ENABLED is
31// defined to a non-zero value, otherwise ADDRESS_SANITIZER_ONLY() is stripped
32// by the preprocessor.
33#if ADDRESS_SANITIZER_ENABLED
34#define ADDRESS_SANITIZER_ONLY(x) x
35#else
36#define ADDRESS_SANITIZER_ONLY(x)
37#endif // ADDRESS_SANITIZER_ENABLED
38
39// Define MEMORY_SANITIZER_ENABLED to 1 if the project was built with the memory
40// sanitizer enabled (-fsanitize=memory).
41#if defined(__SANITIZE_MEMORY__)
42#define MEMORY_SANITIZER_ENABLED 1
43#else // defined(__SANITIZE_MEMORY__)
44#if defined(__clang__)
45#if __has_feature(memory_sanitizer)
46#define MEMORY_SANITIZER_ENABLED 1
47#endif // __has_feature(memory_sanitizer)
48#endif // defined(__clang__)
49#endif // defined(__SANITIZE_MEMORY__)
50
51// MEMORY_SANITIZER_ONLY(X) resolves to X if MEMORY_SANITIZER_ENABLED is defined
52// to a non-zero value, otherwise MEMORY_SANITIZER_ONLY() is stripped by the
53// preprocessor.
54#if MEMORY_SANITIZER_ENABLED
55#define MEMORY_SANITIZER_ONLY(x) x
56#else
57#define MEMORY_SANITIZER_ONLY(x)
58#endif // MEMORY_SANITIZER_ENABLED
59
60// Define THREAD_SANITIZER_ENABLED to 1 if the project was built with the thread
61// sanitizer enabled (-fsanitize=thread).
62#if defined(__SANITIZE_THREAD__)
63#define THREAD_SANITIZER_ENABLED 1
64#else // defined(__SANITIZE_THREAD__)
65#if defined(__clang__)
66#if __has_feature(thread_sanitizer)
67#define THREAD_SANITIZER_ENABLED 1
68#endif // __has_feature(thread_sanitizer)
69#endif // defined(__clang__)
70#endif // defined(__SANITIZE_THREAD__)
71
72// THREAD_SANITIZER_ONLY(X) resolves to X if THREAD_SANITIZER_ENABLED is defined
73// to a non-zero value, otherwise THREAD_SANITIZER_ONLY() is stripped by the
74// preprocessor.
75#if THREAD_SANITIZER_ENABLED
76#define THREAD_SANITIZER_ONLY(x) x
77#else
78#define THREAD_SANITIZER_ONLY(x)
79#endif // THREAD_SANITIZER_ENABLED
80
81// The MSAN_UNPOISON macro marks uninitialized memory as initialized for MSAN.
82// It can be used to suppress false-positive MSAN errors before reading
83// thread-local variables. See https://github.com/google/sanitizers/issues/1265
84#if MEMORY_SANITIZER_ENABLED
85#include <sanitizer/msan_interface.h>
86#define MSAN_UNPOISON(p, size) __msan_unpoison(p, size)
87#else
88#define MSAN_UNPOISON(p, size)
89#endif
90
91#endif // marl_sanitizers_h
92