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 - 6000 0000 0000: protected 20 6000 0000 0000 - 6200 0000 0000: traces 21 6200 0000 0000 - 7d00 0000 0000: - 22 7d00 0000 0000 - 7e00 0000 0000: heap 23 7e00 0000 0000 - 7fff ffff ffff: modules and main thread stack 24 25 C++ COMPAT linux memory layout: 26 0000 0000 0000 - 0400 0000 0000: protected 27 0400 0000 0000 - 1000 0000 0000: shadow 28 1000 0000 0000 - 2900 0000 0000: protected 29 2900 0000 0000 - 2c00 0000 0000: modules 30 2c00 0000 0000 - 6000 0000 0000: - 31 6000 0000 0000 - 6200 0000 0000: traces 32 6200 0000 0000 - 7d00 0000 0000: - 33 7d00 0000 0000 - 7e00 0000 0000: heap 34 7e00 0000 0000 - 7f00 0000 0000: - 35 7f00 0000 0000 - 7fff ffff ffff: main thread stack 36 37 Go linux and darwin memory layout: 38 0000 0000 0000 - 0000 1000 0000: executable 39 0000 1000 0000 - 00f8 0000 0000: - 40 00c0 0000 0000 - 00e0 0000 0000: heap 41 00e0 0000 0000 - 1000 0000 0000: - 42 1000 0000 0000 - 1380 0000 0000: shadow 43 1460 0000 0000 - 6000 0000 0000: - 44 6000 0000 0000 - 6200 0000 0000: traces 45 6200 0000 0000 - 7fff ffff ffff: - 46 47 Go windows memory layout: 48 0000 0000 0000 - 0000 1000 0000: executable 49 0000 1000 0000 - 00f8 0000 0000: - 50 00c0 0000 0000 - 00e0 0000 0000: heap 51 00e0 0000 0000 - 0100 0000 0000: - 52 0100 0000 0000 - 0560 0000 0000: shadow 53 0560 0000 0000 - 0760 0000 0000: traces 54 0760 0000 0000 - 07ff ffff ffff: - 55 */ 56 57 #ifndef TSAN_PLATFORM_H 58 #define TSAN_PLATFORM_H 59 60 #include "tsan_defs.h" 61 #include "tsan_trace.h" 62 63 #if defined(__LP64__) || defined(_WIN64) 64 namespace __tsan { 65 66 #if defined(TSAN_GO) 67 static const uptr kLinuxAppMemBeg = 0x000000000000ULL; 68 static const uptr kLinuxAppMemEnd = 0x04dfffffffffULL; 69 # if SANITIZER_WINDOWS 70 static const uptr kLinuxShadowMsk = 0x010000000000ULL; 71 # else 72 static const uptr kLinuxShadowMsk = 0x200000000000ULL; 73 # endif 74 // TSAN_COMPAT_SHADOW is intended for COMPAT virtual memory layout, 75 // when memory addresses are of the 0x2axxxxxxxxxx form. 76 // The option is enabled with 'setarch x86_64 -L'. 77 #elif defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW 78 static const uptr kLinuxAppMemBeg = 0x290000000000ULL; 79 static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL; 80 #else 81 static const uptr kLinuxAppMemBeg = 0x7cf000000000ULL; 82 static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL; 83 #endif 84 85 static const uptr kLinuxAppMemMsk = 0x7c0000000000ULL; 86 87 #if SANITIZER_WINDOWS 88 const uptr kTraceMemBegin = 0x056000000000ULL; 89 #else 90 const uptr kTraceMemBegin = 0x600000000000ULL; 91 #endif 92 const uptr kTraceMemSize = 0x020000000000ULL; 93 94 // This has to be a macro to allow constant initialization of constants below. 95 #ifndef TSAN_GO 96 #define MemToShadow(addr) \ 97 (((addr) & ~(kLinuxAppMemMsk | (kShadowCell - 1))) * kShadowCnt) 98 #else 99 #define MemToShadow(addr) \ 100 ((((addr) & ~(kShadowCell - 1)) * kShadowCnt) | kLinuxShadowMsk) 101 #endif 102 103 static const uptr kLinuxShadowBeg = MemToShadow(kLinuxAppMemBeg); 104 static const uptr kLinuxShadowEnd = 105 MemToShadow(kLinuxAppMemEnd) | 0xff; 106 107 static inline bool IsAppMem(uptr mem) { 108 return mem >= kLinuxAppMemBeg && mem <= kLinuxAppMemEnd; 109 } 110 111 static inline bool IsShadowMem(uptr mem) { 112 return mem >= kLinuxShadowBeg && mem <= kLinuxShadowEnd; 113 } 114 115 static inline uptr ShadowToMem(uptr shadow) { 116 CHECK(IsShadowMem(shadow)); 117 #ifdef TSAN_GO 118 return (shadow & ~kLinuxShadowMsk) / kShadowCnt; 119 #else 120 return (shadow / kShadowCnt) | kLinuxAppMemMsk; 121 #endif 122 } 123 124 // For COMPAT mapping returns an alternative address 125 // that mapped to the same shadow address. 126 // COMPAT mapping is not quite one-to-one. 127 static inline uptr AlternativeAddress(uptr addr) { 128 #if defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW 129 return (addr & ~kLinuxAppMemMsk) | 0x280000000000ULL; 130 #else 131 return 0; 132 #endif 133 } 134 135 void FlushShadowMemory(); 136 void WriteMemoryProfile(char *buf, uptr buf_size); 137 138 const char *InitializePlatform(); 139 void FinalizePlatform(); 140 uptr ALWAYS_INLINE GetThreadTrace(int tid) { 141 uptr p = kTraceMemBegin + (uptr)(tid * 2) * kTraceSize * sizeof(Event); 142 DCHECK_LT(p, kTraceMemBegin + kTraceMemSize); 143 return p; 144 } 145 146 uptr ALWAYS_INLINE GetThreadTraceHeader(int tid) { 147 uptr p = kTraceMemBegin + (uptr)(tid * 2 + 1) * kTraceSize * sizeof(Event); 148 DCHECK_LT(p, kTraceMemBegin + kTraceMemSize); 149 return p; 150 } 151 152 void internal_start_thread(void(*func)(void*), void *arg); 153 154 // Says whether the addr relates to a global var. 155 // Guesses with high probability, may yield both false positives and negatives. 156 bool IsGlobalVar(uptr addr); 157 int ExtractResolvFDs(void *state, int *fds, int nfd); 158 159 } // namespace __tsan 160 161 #else // defined(__LP64__) || defined(_WIN64) 162 # error "Only 64-bit is supported" 163 #endif 164 165 #endif // TSAN_PLATFORM_H 166