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