Home | History | Annotate | Line # | Download | only in tsan
      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 
     68 inline Epoch EpochInc(Epoch epoch) {
     69   return static_cast<Epoch>(static_cast<u16>(epoch) + 1);
     70 }
     71 
     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 
    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>
    123 T min(T a, T b) {
    124   return a < b ? a : b;
    125 }
    126 
    127 template<typename T>
    128 T max(T a, T b) {
    129   return a > b ? a : b;
    130 }
    131 
    132 template<typename T>
    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>
    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>
    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