1 //===-- tsan_platform.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 // Platform-specific code. 13 //===----------------------------------------------------------------------===// 14 15 /* 16 C++ linux memory layout: 17 0000 0000 0000 - 03c0 0000 0000: protected 18 03c0 0000 0000 - 1000 0000 0000: shadow 19 1000 0000 0000 - 3000 0000 0000: protected 20 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects) 21 4000 0000 0000 - 6000 0000 0000: protected 22 6000 0000 0000 - 6200 0000 0000: traces 23 6200 0000 0000 - 7d00 0000 0000: - 24 7d00 0000 0000 - 7e00 0000 0000: heap 25 7e00 0000 0000 - 7fff ffff ffff: modules and main thread stack 26 27 C++ COMPAT linux memory layout: 28 0000 0000 0000 - 0400 0000 0000: protected 29 0400 0000 0000 - 1000 0000 0000: shadow 30 1000 0000 0000 - 2900 0000 0000: protected 31 2900 0000 0000 - 2c00 0000 0000: modules 32 2c00 0000 0000 - 3000 0000 0000: - 33 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects) 34 4000 0000 0000 - 6000 0000 0000: - 35 6000 0000 0000 - 6200 0000 0000: traces 36 6200 0000 0000 - 7d00 0000 0000: - 37 7d00 0000 0000 - 7e00 0000 0000: heap 38 7e00 0000 0000 - 7f00 0000 0000: - 39 7f00 0000 0000 - 7fff ffff ffff: main thread stack 40 41 Go linux and darwin memory layout: 42 0000 0000 0000 - 0000 1000 0000: executable 43 0000 1000 0000 - 00f8 0000 0000: - 44 00c0 0000 0000 - 00e0 0000 0000: heap 45 00e0 0000 0000 - 1000 0000 0000: - 46 1000 0000 0000 - 1380 0000 0000: shadow 47 1460 0000 0000 - 2000 0000 0000: - 48 3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects) 49 4000 0000 0000 - 6000 0000 0000: - 50 6000 0000 0000 - 6200 0000 0000: traces 51 6200 0000 0000 - 7fff ffff ffff: - 52 53 Go windows memory layout: 54 0000 0000 0000 - 0000 1000 0000: executable 55 0000 1000 0000 - 00f8 0000 0000: - 56 00c0 0000 0000 - 00e0 0000 0000: heap 57 00e0 0000 0000 - 0100 0000 0000: - 58 0100 0000 0000 - 0560 0000 0000: shadow 59 0560 0000 0000 - 0760 0000 0000: traces 60 0760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects) 61 07d0 0000 0000 - 07ff ffff ffff: - 62 */ 63 64 #ifndef TSAN_PLATFORM_H 65 #define TSAN_PLATFORM_H 66 67 #include "tsan_defs.h" 68 #include "tsan_trace.h" 69 70 #if defined(__LP64__) || defined(_WIN64) 71 namespace __tsan { 72 73 #if defined(TSAN_GO) 74 static const uptr kLinuxAppMemBeg = 0x000000000000ULL; 75 static const uptr kLinuxAppMemEnd = 0x04dfffffffffULL; 76 # if SANITIZER_WINDOWS 77 static const uptr kLinuxShadowMsk = 0x010000000000ULL; 78 static const uptr kMetaShadow = 0x076000000000ULL; 79 static const uptr kMetaSize = 0x007000000000ULL; 80 # else // if SANITIZER_WINDOWS 81 static const uptr kLinuxShadowMsk = 0x200000000000ULL; 82 static const uptr kMetaShadow = 0x300000000000ULL; 83 static const uptr kMetaSize = 0x100000000000ULL; 84 # endif // if SANITIZER_WINDOWS 85 #else // defined(TSAN_GO) 86 static const uptr kMetaShadow = 0x300000000000ULL; 87 static const uptr kMetaSize = 0x100000000000ULL; 88 // TSAN_COMPAT_SHADOW is intended for COMPAT virtual memory layout, 89 // when memory addresses are of the 0x2axxxxxxxxxx form. 90 // The option is enabled with 'setarch x86_64 -L'. 91 # if defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW 92 static const uptr kLinuxAppMemBeg = 0x290000000000ULL; 93 static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL; 94 static const uptr kAppMemGapBeg = 0x2c0000000000ULL; 95 static const uptr kAppMemGapEnd = 0x7d0000000000ULL; 96 # else 97 static const uptr kLinuxAppMemBeg = 0x7cf000000000ULL; 98 static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL; 99 # endif 100 #endif 101 102 static const uptr kLinuxAppMemMsk = 0x7c0000000000ULL; 103 104 #if SANITIZER_WINDOWS 105 const uptr kTraceMemBegin = 0x056000000000ULL; 106 #else 107 const uptr kTraceMemBegin = 0x600000000000ULL; 108 #endif 109 const uptr kTraceMemSize = 0x020000000000ULL; 110 111 // This has to be a macro to allow constant initialization of constants below. 112 #ifndef TSAN_GO 113 #define MemToShadow(addr) \ 114 ((((uptr)addr) & ~(kLinuxAppMemMsk | (kShadowCell - 1))) * kShadowCnt) 115 #define MemToMeta(addr) \ 116 (u32*)(((((uptr)addr) & ~(kLinuxAppMemMsk | (kMetaShadowCell - 1))) \ 117 / kMetaShadowCell * kMetaShadowSize) | kMetaShadow) 118 #else 119 #define MemToShadow(addr) \ 120 (((((uptr)addr) & ~(kShadowCell - 1)) * kShadowCnt) | kLinuxShadowMsk) 121 #define MemToMeta(addr) \ 122 (u32*)(((((uptr)addr) & ~(kMetaShadowCell - 1)) \ 123 / kMetaShadowCell * kMetaShadowSize) | kMetaShadow) 124 #endif 125 126 static const uptr kLinuxShadowBeg = MemToShadow(kLinuxAppMemBeg); 127 static const uptr kLinuxShadowEnd = 128 MemToShadow(kLinuxAppMemEnd) | 0xff; 129 130 static inline bool IsAppMem(uptr mem) { 131 #if defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW 132 return (mem >= kLinuxAppMemBeg && mem < kAppMemGapBeg) || 133 (mem >= kAppMemGapEnd && mem <= kLinuxAppMemEnd); 134 #elif defined(TSAN_GO) 135 return mem <= kLinuxAppMemEnd; 136 #else 137 return mem >= kLinuxAppMemBeg && mem <= kLinuxAppMemEnd; 138 #endif 139 } 140 141 static inline bool IsShadowMem(uptr mem) { 142 return mem >= kLinuxShadowBeg && mem <= kLinuxShadowEnd; 143 } 144 145 static inline uptr ShadowToMem(uptr shadow) { 146 CHECK(IsShadowMem(shadow)); 147 #ifdef TSAN_GO 148 return (shadow & ~kLinuxShadowMsk) / kShadowCnt; 149 #else 150 return (shadow / kShadowCnt) | kLinuxAppMemMsk; 151 #endif 152 } 153 154 // For COMPAT mapping returns an alternative address 155 // that mapped to the same shadow address. 156 // COMPAT mapping is not quite one-to-one. 157 static inline uptr AlternativeAddress(uptr addr) { 158 #if defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW 159 return (addr & ~kLinuxAppMemMsk) | 0x280000000000ULL; 160 #else 161 return 0; 162 #endif 163 } 164 165 void FlushShadowMemory(); 166 void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive); 167 uptr GetRSS(); 168 169 const char *InitializePlatform(); 170 void FinalizePlatform(); 171 172 // The additional page is to catch shadow stack overflow as paging fault. 173 // Windows wants 64K alignment for mmaps. 174 const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace) 175 + (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1); 176 177 uptr ALWAYS_INLINE GetThreadTrace(int tid) { 178 uptr p = kTraceMemBegin + (uptr)tid * kTotalTraceSize; 179 DCHECK_LT(p, kTraceMemBegin + kTraceMemSize); 180 return p; 181 } 182 183 uptr ALWAYS_INLINE GetThreadTraceHeader(int tid) { 184 uptr p = kTraceMemBegin + (uptr)tid * kTotalTraceSize 185 + kTraceSize * sizeof(Event); 186 DCHECK_LT(p, kTraceMemBegin + kTraceMemSize); 187 return p; 188 } 189 190 void *internal_start_thread(void(*func)(void*), void *arg); 191 void internal_join_thread(void *th); 192 193 // Says whether the addr relates to a global var. 194 // Guesses with high probability, may yield both false positives and negatives. 195 bool IsGlobalVar(uptr addr); 196 int ExtractResolvFDs(void *state, int *fds, int nfd); 197 int ExtractRecvmsgFDs(void *msg, int *fds, int nfd); 198 199 int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, 200 void *abstime), void *c, void *m, void *abstime, 201 void(*cleanup)(void *arg), void *arg); 202 203 } // namespace __tsan 204 205 #else // defined(__LP64__) || defined(_WIN64) 206 # error "Only 64-bit is supported" 207 #endif 208 209 #endif // TSAN_PLATFORM_H 210