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