1 //===-- tsan_defs.h ---------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of ThreadSanitizer (TSan), a race detector. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef TSAN_DEFS_H 14 #define TSAN_DEFS_H 15 16 #include "sanitizer_common/sanitizer_internal_defs.h" 17 #include "sanitizer_common/sanitizer_libc.h" 18 #include "sanitizer_common/sanitizer_mutex.h" 19 #include "ubsan/ubsan_platform.h" 20 21 #ifndef TSAN_VECTORIZE 22 # define TSAN_VECTORIZE __SSE4_2__ 23 #endif 24 25 #if TSAN_VECTORIZE 26 // <emmintrin.h> transitively includes <stdlib.h>, 27 // and it's prohibited to include std headers into tsan runtime. 28 // So we do this dirty trick. 29 # define _MM_MALLOC_H_INCLUDED 30 # define __MM_MALLOC_H 31 # include <emmintrin.h> 32 # include <smmintrin.h> 33 # define VECTOR_ALIGNED ALIGNED(16) 34 typedef __m128i m128; 35 #else 36 # define VECTOR_ALIGNED 37 #endif 38 39 // Setup defaults for compile definitions. 40 #ifndef TSAN_NO_HISTORY 41 # define TSAN_NO_HISTORY 0 42 #endif 43 44 #ifndef TSAN_CONTAINS_UBSAN 45 # if CAN_SANITIZE_UB && !SANITIZER_GO 46 # define TSAN_CONTAINS_UBSAN 1 47 # else 48 # define TSAN_CONTAINS_UBSAN 0 49 # endif 50 #endif 51 52 namespace __tsan { 53 54 constexpr uptr kByteBits = 8; 55 56 // Thread slot ID. 57 enum class Sid : u8 {}; 58 constexpr uptr kThreadSlotCount = 256; 59 constexpr Sid kFreeSid = static_cast<Sid>(255); 60 61 // Abstract time unit, vector clock element. 62 enum class Epoch : u16 {}; 63 constexpr uptr kEpochBits = 14; 64 constexpr Epoch kEpochZero = static_cast<Epoch>(0); 65 constexpr Epoch kEpochOver = static_cast<Epoch>(1 << kEpochBits); 66 67 const int kClkBits = 42; 68 const unsigned kMaxTidReuse = (1 << (64 - kClkBits)) - 1; 69 70 struct ClockElem { 71 u64 epoch : kClkBits; 72 u64 reused : 64 - kClkBits; // tid reuse count 73 }; 74 75 struct ClockBlock { 76 static const uptr kSize = 512; 77 static const uptr kTableSize = kSize / sizeof(u32); 78 static const uptr kClockCount = kSize / sizeof(ClockElem); 79 static const uptr kRefIdx = kTableSize - 1; 80 static const uptr kBlockIdx = kTableSize - 2; 81 82 union { 83 u32 table[kTableSize]; 84 ClockElem clock[kClockCount]; 85 }; 86 87 ClockBlock() { 88 } 89 }; 90 91 const int kTidBits = 13; 92 // Reduce kMaxTid by kClockCount because one slot in ClockBlock table is 93 // occupied by reference counter, so total number of elements we can store 94 // in SyncClock is kClockCount * (kTableSize - 1). 95 const unsigned kMaxTid = (1 << kTidBits) - ClockBlock::kClockCount; 96 #if !SANITIZER_GO 97 const unsigned kMaxTidInClock = kMaxTid * 2; // This includes msb 'freed' bit. 98 #else 99 const unsigned kMaxTidInClock = kMaxTid; // Go does not track freed memory. 100 #endif 101 const uptr kShadowStackSize = 64 * 1024; 102 103 // Count of shadow values in a shadow cell. 104 const uptr kShadowCnt = 4; 105 106 // That many user bytes are mapped onto a single shadow cell. 107 const uptr kShadowCell = 8; 108 109 // Single shadow value. 110 typedef u64 RawShadow; 111 const uptr kShadowSize = sizeof(RawShadow); 112 113 // Shadow memory is kShadowMultiplier times larger than user memory. 114 const uptr kShadowMultiplier = kShadowSize * kShadowCnt / kShadowCell; 115 116 // That many user bytes are mapped onto a single meta shadow cell. 117 // Must be less or equal to minimal memory allocator alignment. 118 const uptr kMetaShadowCell = 8; 119 120 // Size of a single meta shadow value (u32). 121 const uptr kMetaShadowSize = 4; 122 123 // All addresses and PCs are assumed to be compressable to that many bits. 124 const uptr kCompressedAddrBits = 44; 125 126 #if TSAN_NO_HISTORY 127 const bool kCollectHistory = false; 128 #else 129 const bool kCollectHistory = true; 130 #endif 131 132 // The following "build consistency" machinery ensures that all source files 133 // are built in the same configuration. Inconsistent builds lead to 134 // hard to debug crashes. 135 #if SANITIZER_DEBUG 136 void build_consistency_debug(); 137 #else 138 void build_consistency_release(); 139 #endif 140 141 static inline void USED build_consistency() { 142 #if SANITIZER_DEBUG 143 build_consistency_debug(); 144 #else 145 build_consistency_release(); 146 #endif 147 } 148 149 template<typename T> 150 T min(T a, T b) { 151 return a < b ? a : b; 152 } 153 154 template<typename T> 155 T max(T a, T b) { 156 return a > b ? a : b; 157 } 158 159 template<typename T> 160 T RoundUp(T p, u64 align) { 161 DCHECK_EQ(align & (align - 1), 0); 162 return (T)(((u64)p + align - 1) & ~(align - 1)); 163 } 164 165 template<typename T> 166 T RoundDown(T p, u64 align) { 167 DCHECK_EQ(align & (align - 1), 0); 168 return (T)((u64)p & ~(align - 1)); 169 } 170 171 // Zeroizes high part, returns 'bits' lsb bits. 172 template<typename T> 173 T GetLsb(T v, int bits) { 174 return (T)((u64)v & ((1ull << bits) - 1)); 175 } 176 177 struct MD5Hash { 178 u64 hash[2]; 179 bool operator==(const MD5Hash &other) const; 180 }; 181 182 MD5Hash md5_hash(const void *data, uptr size); 183 184 struct Processor; 185 struct ThreadState; 186 class ThreadContext; 187 struct Context; 188 struct ReportStack; 189 class ReportDesc; 190 class RegionAlloc; 191 192 typedef uptr AccessType; 193 194 enum : AccessType { 195 kAccessWrite = 0, 196 kAccessRead = 1 << 0, 197 kAccessAtomic = 1 << 1, 198 kAccessVptr = 1 << 2, // read or write of an object virtual table pointer 199 kAccessFree = 1 << 3, // synthetic memory access during memory freeing 200 kAccessExternalPC = 1 << 4, // access PC can have kExternalPCBit set 201 }; 202 203 // Descriptor of user's memory block. 204 struct MBlock { 205 u64 siz : 48; 206 u64 tag : 16; 207 StackID stk; 208 Tid tid; 209 }; 210 211 COMPILER_CHECK(sizeof(MBlock) == 16); 212 213 enum ExternalTag : uptr { 214 kExternalTagNone = 0, 215 kExternalTagSwiftModifyingAccess = 1, 216 kExternalTagFirstUserAvailable = 2, 217 kExternalTagMax = 1024, 218 // Don't set kExternalTagMax over 65,536, since MBlock only stores tags 219 // as 16-bit values, see tsan_defs.h. 220 }; 221 222 enum MutexType { 223 MutexTypeTrace = MutexLastCommon, 224 MutexTypeReport, 225 MutexTypeSyncVar, 226 MutexTypeAnnotations, 227 MutexTypeAtExit, 228 MutexTypeFired, 229 MutexTypeRacy, 230 MutexTypeGlobalProc, 231 }; 232 233 } // namespace __tsan 234 235 #endif // TSAN_DEFS_H 236