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 constexpr Epoch kEpochLast = static_cast<Epoch>((1 << kEpochBits) - 1);
67 
EpochInc(Epoch epoch)68 inline Epoch EpochInc(Epoch epoch) {
69   return static_cast<Epoch>(static_cast<u16>(epoch) + 1);
70 }
71 
EpochOverflow(Epoch epoch)72 inline bool EpochOverflow(Epoch epoch) { return epoch == kEpochOver; }
73 
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 // Single shadow value.
83 enum class RawShadow : u32 {};
84 const uptr kShadowSize = sizeof(RawShadow);
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 // All addresses and PCs are assumed to be compressable to that many bits.
97 const uptr kCompressedAddrBits = 44;
98 
99 #if TSAN_NO_HISTORY
100 const bool kCollectHistory = false;
101 #else
102 const bool kCollectHistory = true;
103 #endif
104 
105 // The following "build consistency" machinery ensures that all source files
106 // are built in the same configuration. Inconsistent builds lead to
107 // hard to debug crashes.
108 #if SANITIZER_DEBUG
109 void build_consistency_debug();
110 #else
111 void build_consistency_release();
112 #endif
113 
build_consistency()114 static inline void USED build_consistency() {
115 #if SANITIZER_DEBUG
116   build_consistency_debug();
117 #else
118   build_consistency_release();
119 #endif
120 }
121 
122 template<typename T>
min(T a,T b)123 T min(T a, T b) {
124   return a < b ? a : b;
125 }
126 
127 template<typename T>
max(T a,T b)128 T max(T a, T b) {
129   return a > b ? a : b;
130 }
131 
132 template<typename T>
RoundUp(T p,u64 align)133 T RoundUp(T p, u64 align) {
134   DCHECK_EQ(align & (align - 1), 0);
135   return (T)(((u64)p + align - 1) & ~(align - 1));
136 }
137 
138 template<typename T>
RoundDown(T p,u64 align)139 T RoundDown(T p, u64 align) {
140   DCHECK_EQ(align & (align - 1), 0);
141   return (T)((u64)p & ~(align - 1));
142 }
143 
144 // Zeroizes high part, returns 'bits' lsb bits.
145 template<typename T>
GetLsb(T v,int bits)146 T GetLsb(T v, int bits) {
147   return (T)((u64)v & ((1ull << bits) - 1));
148 }
149 
150 struct MD5Hash {
151   u64 hash[2];
152   bool operator==(const MD5Hash &other) const;
153 };
154 
155 MD5Hash md5_hash(const void *data, uptr size);
156 
157 struct Processor;
158 struct ThreadState;
159 class ThreadContext;
160 struct TidSlot;
161 struct Context;
162 struct ReportStack;
163 class ReportDesc;
164 class RegionAlloc;
165 struct Trace;
166 struct TracePart;
167 
168 typedef uptr AccessType;
169 
170 enum : AccessType {
171   kAccessWrite = 0,
172   kAccessRead = 1 << 0,
173   kAccessAtomic = 1 << 1,
174   kAccessVptr = 1 << 2,  // read or write of an object virtual table pointer
175   kAccessFree = 1 << 3,  // synthetic memory access during memory freeing
176   kAccessExternalPC = 1 << 4,  // access PC can have kExternalPCBit set
177   kAccessCheckOnly = 1 << 5,   // check for races, but don't store
178   kAccessNoRodata = 1 << 6,    // don't check for .rodata marker
179   kAccessSlotLocked = 1 << 7,  // memory access with TidSlot locked
180 };
181 
182 // Descriptor of user's memory block.
183 struct MBlock {
184   u64  siz : 48;
185   u64  tag : 16;
186   StackID stk;
187   Tid tid;
188 };
189 
190 COMPILER_CHECK(sizeof(MBlock) == 16);
191 
192 enum ExternalTag : uptr {
193   kExternalTagNone = 0,
194   kExternalTagSwiftModifyingAccess = 1,
195   kExternalTagFirstUserAvailable = 2,
196   kExternalTagMax = 1024,
197   // Don't set kExternalTagMax over 65,536, since MBlock only stores tags
198   // as 16-bit values, see tsan_defs.h.
199 };
200 
201 enum {
202   MutexTypeReport = MutexLastCommon,
203   MutexTypeSyncVar,
204   MutexTypeAnnotations,
205   MutexTypeAtExit,
206   MutexTypeFired,
207   MutexTypeRacy,
208   MutexTypeGlobalProc,
209   MutexTypeInternalAlloc,
210   MutexTypeTrace,
211   MutexTypeSlot,
212   MutexTypeSlots,
213 };
214 
215 }  // namespace __tsan
216 
217 #endif  // TSAN_DEFS_H
218