218 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of ThreadSanitizer (TSan), a race detector.10//11//===----------------------------------------------------------------------===//12 13#ifndef TSAN_DEFS_H14#define TSAN_DEFS_H15 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_VECTORIZE22# define TSAN_VECTORIZE __SSE4_2__23#endif24 25#if TSAN_VECTORIZE26// <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_INCLUDED30# define __MM_MALLOC_H31# include <emmintrin.h>32# include <smmintrin.h>33# define VECTOR_ALIGNED alignas(16)34typedef __m128i m128;35#else36# define VECTOR_ALIGNED37#endif38 39// Setup defaults for compile definitions.40#ifndef TSAN_NO_HISTORY41# define TSAN_NO_HISTORY 042#endif43 44#ifndef TSAN_CONTAINS_UBSAN45# if CAN_SANITIZE_UB && !SANITIZER_GO46# define TSAN_CONTAINS_UBSAN 147# else48# define TSAN_CONTAINS_UBSAN 049# endif50#endif51 52namespace __tsan {53 54constexpr uptr kByteBits = 8;55 56// Thread slot ID.57enum class Sid : u8 {};58constexpr uptr kThreadSlotCount = 256;59constexpr Sid kFreeSid = static_cast<Sid>(255);60 61// Abstract time unit, vector clock element.62enum class Epoch : u16 {};63constexpr uptr kEpochBits = 14;64constexpr Epoch kEpochZero = static_cast<Epoch>(0);65constexpr Epoch kEpochOver = static_cast<Epoch>(1 << kEpochBits);66constexpr Epoch kEpochLast = static_cast<Epoch>((1 << kEpochBits) - 1);67 68inline Epoch EpochInc(Epoch epoch) {69 return static_cast<Epoch>(static_cast<u16>(epoch) + 1);70}71 72inline bool EpochOverflow(Epoch epoch) { return epoch == kEpochOver; }73 74const uptr kShadowStackSize = 64 * 1024;75 76// Count of shadow values in a shadow cell.77const uptr kShadowCnt = 4;78 79// That many user bytes are mapped onto a single shadow cell.80const uptr kShadowCell = 8;81 82// Single shadow value.83enum class RawShadow : u32 {};84const uptr kShadowSize = sizeof(RawShadow);85 86// Shadow memory is kShadowMultiplier times larger than user memory.87const 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.91const uptr kMetaShadowCell = 8;92 93// Size of a single meta shadow value (u32).94const uptr kMetaShadowSize = 4;95 96// All addresses and PCs are assumed to be compressable to that many bits.97const uptr kCompressedAddrBits = 44;98 99#if TSAN_NO_HISTORY100const bool kCollectHistory = false;101#else102const bool kCollectHistory = true;103#endif104 105// The following "build consistency" machinery ensures that all source files106// are built in the same configuration. Inconsistent builds lead to107// hard to debug crashes.108#if SANITIZER_DEBUG109void build_consistency_debug();110#else111void build_consistency_release();112#endif113 114static inline void USED build_consistency() {115#if SANITIZER_DEBUG116 build_consistency_debug();117#else118 build_consistency_release();119#endif120}121 122template<typename T>123T min(T a, T b) {124 return a < b ? a : b;125}126 127template<typename T>128T max(T a, T b) {129 return a > b ? a : b;130}131 132template<typename T>133T RoundUp(T p, u64 align) {134 DCHECK_EQ(align & (align - 1), 0);135 return (T)(((u64)p + align - 1) & ~(align - 1));136}137 138template<typename T>139T 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.145template<typename T>146T GetLsb(T v, int bits) {147 return (T)((u64)v & ((1ull << bits) - 1));148}149 150struct MD5Hash {151 u64 hash[2];152 bool operator==(const MD5Hash &other) const;153};154 155MD5Hash md5_hash(const void *data, uptr size);156 157struct Processor;158struct ThreadState;159class ThreadContext;160struct TidSlot;161struct Context;162struct ReportStack;163class ReportDesc;164class RegionAlloc;165struct Trace;166struct TracePart;167 168typedef uptr AccessType;169 170enum : AccessType {171 kAccessWrite = 0,172 kAccessRead = 1 << 0,173 kAccessAtomic = 1 << 1,174 kAccessVptr = 1 << 2, // read or write of an object virtual table pointer175 kAccessFree = 1 << 3, // synthetic memory access during memory freeing176 kAccessExternalPC = 1 << 4, // access PC can have kExternalPCBit set177 kAccessCheckOnly = 1 << 5, // check for races, but don't store178 kAccessNoRodata = 1 << 6, // don't check for .rodata marker179 kAccessSlotLocked = 1 << 7, // memory access with TidSlot locked180};181 182// Descriptor of user's memory block.183struct MBlock {184 u64 siz : 48;185 u64 tag : 16;186 StackID stk;187 Tid tid;188};189 190COMPILER_CHECK(sizeof(MBlock) == 16);191 192enum 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 tags198 // as 16-bit values, see tsan_defs.h.199};200 201enum {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 __tsan216 217#endif // TSAN_DEFS_H218