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 "tsan_stat.h" 19 #include "ubsan/ubsan_platform.h" 20 21 // Setup defaults for compile definitions. 22 #ifndef TSAN_NO_HISTORY 23 # define TSAN_NO_HISTORY 0 24 #endif 25 26 #ifndef TSAN_COLLECT_STATS 27 # define TSAN_COLLECT_STATS 0 28 #endif 29 30 #ifndef TSAN_CONTAINS_UBSAN 31 # if CAN_SANITIZE_UB && !SANITIZER_GO 32 # define TSAN_CONTAINS_UBSAN 1 33 # else 34 # define TSAN_CONTAINS_UBSAN 0 35 # endif 36 #endif 37 38 namespace __tsan { 39 40 const int kClkBits = 42; 41 const unsigned kMaxTidReuse = (1 << (64 - kClkBits)) - 1; 42 43 struct ClockElem { 44 u64 epoch : kClkBits; 45 u64 reused : 64 - kClkBits; // tid reuse count 46 }; 47 48 struct ClockBlock { 49 static const uptr kSize = 512; 50 static const uptr kTableSize = kSize / sizeof(u32); 51 static const uptr kClockCount = kSize / sizeof(ClockElem); 52 static const uptr kRefIdx = kTableSize - 1; 53 static const uptr kBlockIdx = kTableSize - 2; 54 55 union { 56 u32 table[kTableSize]; 57 ClockElem clock[kClockCount]; 58 }; 59 60 ClockBlock() { 61 } 62 }; 63 64 const int kTidBits = 13; 65 // Reduce kMaxTid by kClockCount because one slot in ClockBlock table is 66 // occupied by reference counter, so total number of elements we can store 67 // in SyncClock is kClockCount * (kTableSize - 1). 68 const unsigned kMaxTid = (1 << kTidBits) - ClockBlock::kClockCount; 69 #if !SANITIZER_GO 70 const unsigned kMaxTidInClock = kMaxTid * 2; // This includes msb 'freed' bit. 71 #else 72 const unsigned kMaxTidInClock = kMaxTid; // Go does not track freed memory. 73 #endif 74 const uptr kShadowStackSize = 64 * 1024; 75 76 // Count of shadow values in a shadow cell. 77 const uptr kShadowCnt = 4; 78 79 // That many user bytes are mapped onto a single shadow cell. 80 const uptr kShadowCell = 8; 81 82 // Size of a single shadow value (u64). 83 const uptr kShadowSize = 8; 84 85 // Shadow memory is kShadowMultiplier times larger than user memory. 86 const uptr kShadowMultiplier = kShadowSize * kShadowCnt / kShadowCell; 87 88 // That many user bytes are mapped onto a single meta shadow cell. 89 // Must be less or equal to minimal memory allocator alignment. 90 const uptr kMetaShadowCell = 8; 91 92 // Size of a single meta shadow value (u32). 93 const uptr kMetaShadowSize = 4; 94 95 #if TSAN_NO_HISTORY 96 const bool kCollectHistory = false; 97 #else 98 const bool kCollectHistory = true; 99 #endif 100 101 const u16 kInvalidTid = kMaxTid + 1; 102 103 // The following "build consistency" machinery ensures that all source files 104 // are built in the same configuration. Inconsistent builds lead to 105 // hard to debug crashes. 106 #if SANITIZER_DEBUG 107 void build_consistency_debug(); 108 #else 109 void build_consistency_release(); 110 #endif 111 112 #if TSAN_COLLECT_STATS 113 void build_consistency_stats(); 114 #else 115 void build_consistency_nostats(); 116 #endif 117 118 static inline void USED build_consistency() { 119 #if SANITIZER_DEBUG 120 build_consistency_debug(); 121 #else 122 build_consistency_release(); 123 #endif 124 #if TSAN_COLLECT_STATS 125 build_consistency_stats(); 126 #else 127 build_consistency_nostats(); 128 #endif 129 } 130 131 template<typename T> 132 T min(T a, T b) { 133 return a < b ? a : b; 134 } 135 136 template<typename T> 137 T max(T a, T b) { 138 return a > b ? a : b; 139 } 140 141 template<typename T> 142 T RoundUp(T p, u64 align) { 143 DCHECK_EQ(align & (align - 1), 0); 144 return (T)(((u64)p + align - 1) & ~(align - 1)); 145 } 146 147 template<typename T> 148 T RoundDown(T p, u64 align) { 149 DCHECK_EQ(align & (align - 1), 0); 150 return (T)((u64)p & ~(align - 1)); 151 } 152 153 // Zeroizes high part, returns 'bits' lsb bits. 154 template<typename T> 155 T GetLsb(T v, int bits) { 156 return (T)((u64)v & ((1ull << bits) - 1)); 157 } 158 159 struct MD5Hash { 160 u64 hash[2]; 161 bool operator==(const MD5Hash &other) const; 162 }; 163 164 MD5Hash md5_hash(const void *data, uptr size); 165 166 struct Processor; 167 struct ThreadState; 168 class ThreadContext; 169 struct Context; 170 struct ReportStack; 171 class ReportDesc; 172 class RegionAlloc; 173 174 // Descriptor of user's memory block. 175 struct MBlock { 176 u64 siz : 48; 177 u64 tag : 16; 178 u32 stk; 179 u16 tid; 180 }; 181 182 COMPILER_CHECK(sizeof(MBlock) == 16); 183 184 enum ExternalTag : uptr { 185 kExternalTagNone = 0, 186 kExternalTagSwiftModifyingAccess = 1, 187 kExternalTagFirstUserAvailable = 2, 188 kExternalTagMax = 1024, 189 // Don't set kExternalTagMax over 65,536, since MBlock only stores tags 190 // as 16-bit values, see tsan_defs.h. 191 }; 192 193 } // namespace __tsan 194 195 #endif // TSAN_DEFS_H 196